Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/DumpResponse.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/DumpResponse.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/DumpResponse.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,77 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.List; + +/** + * A response from one of the dump.* commands. These are formatted differently + * than responses from other commands. Most dump commands return List. + * `dump.fabric_nodes' is a notable exception returning a list of Fabric host/port pairs + * as strings. + */ +public class DumpResponse { + private List returnValue; + private int ttl; + + public DumpResponse(List responseData) { + // uuid ignored (why is it int?) + // version token ignored + this.ttl = (Integer)responseData.get(2); + this.returnValue = (List)responseData.get(3); + } + + public List getReturnValue() { + return this.returnValue; + } + + public int getTtl() { + return this.ttl; + } + + /** + * Debug method to print the response and classes of data values. + */ + public String dumpReturnValue() { + StringBuffer b = new StringBuffer(); + if (this.returnValue.size() > 0 && + List.class.isAssignableFrom(this.returnValue.get(0).getClass())) { + // elements of return value list are lists themselves + for (List l : (List) this.returnValue) { + b.append("[\n"); + for (Object o : l) { + b.append(" " + o.toString()); + b.append(" (" + o.getClass() + "),\n"); + } + b.append("]\n"); + } + } else { + // for dump.fabric_nodes or any other non-list value types + for (Object o : this.returnValue) { + b.append(o.toString() + ","); + } + } + return b.toString(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricCommunicationException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricCommunicationException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricCommunicationException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,45 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +/** + * Indicates an exceptional condition while communicating with + * a Fabric server. + */ +public class FabricCommunicationException extends Exception { + + private static final long serialVersionUID = 1L; + + public FabricCommunicationException(Throwable cause) { + super(cause); + } + + public FabricCommunicationException(String message) { + super(message); + } + + public FabricCommunicationException(String message, Throwable cause) { + super(message, cause); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,115 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.mysql.fabric.proto.xmlrpc.XmlRpcClient; + +public class FabricConnection { + private XmlRpcClient client; + + // internal caches + private Map shardMappingsByTableName = new HashMap(); + private Map serverGroupsByName = new HashMap(); + private long shardMappingsExpiration; + private long serverGroupsExpiration; + + public FabricConnection(String url, String username, String password) throws FabricCommunicationException { + this.client = new XmlRpcClient(url, username, password); + refreshState(); + } + + /** + * + * @param urls + * @param username + * @param password + * @throws FabricCommunicationException + */ + public FabricConnection(Set urls, String username, String password) throws FabricCommunicationException { + throw new UnsupportedOperationException("Multiple connections not supported."); + } + + public String getInstanceUuid() { + return null; + } + + public int getVersion() { + return 0; + } + + /** + * + * @return version of state data + */ + public int refreshState() throws FabricCommunicationException { + FabricStateResponse> serverGroups = this.client.getServerGroups(); + FabricStateResponse> shardMappings = this.client.getShardMappings(); + serverGroupsExpiration = serverGroups.getExpireTimeMillis(); + shardMappingsExpiration = shardMappings.getExpireTimeMillis(); + + for (ServerGroup g : serverGroups.getData()) { + this.serverGroupsByName.put(g.getName(), g); + } + + for (ShardMapping m : shardMappings.getData()) { + // a shard mapping may be associated with more than one table + for (ShardTable t : m.getShardTables()) { + this.shardMappingsByTableName.put(t.getDatabase() + "." + t.getTable(), m); + } + } + + return 0; + } + + public ServerGroup getServerGroup(String serverGroupName) throws FabricCommunicationException { + if (isStateExpired()) { + refreshState(); + } + return this.serverGroupsByName.get(serverGroupName); + } + + public ShardMapping getShardMapping(String database, String table) throws FabricCommunicationException { + if (isStateExpired()) { + refreshState(); + } + return this.shardMappingsByTableName.get(database + "." + table); + } + + public boolean isStateExpired() { + return System.currentTimeMillis() > shardMappingsExpiration || + System.currentTimeMillis() > serverGroupsExpiration; + } + + public Set getFabricHosts() { + return null; + } + + public XmlRpcClient getClient() { + return this.client; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricStateResponse.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricStateResponse.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/FabricStateResponse.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,50 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +public class FabricStateResponse { + private T data; + private long expireTimeMillis; + + public FabricStateResponse(T data, int secsTtl) { + this.data = data; + this.expireTimeMillis = System.currentTimeMillis() + (1000 * secsTtl); + } + + public FabricStateResponse(T data, long expireTimeMillis) { + this.data = data; + this.expireTimeMillis = expireTimeMillis; + } + + public T getData() { + return this.data; + } + + /** + * The expiration time of this data. Should be compared to {@link System.currentTimeMillis()}. + */ + public long getExpireTimeMillis() { + return this.expireTimeMillis; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/HashShardMapping.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/HashShardMapping.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/HashShardMapping.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,80 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/** + * A shard mapping with ranges defined by hashing key values. Lookups work essentially + * the same as in {@link RangeShardMapping} but strings are compared as opposed to ints. + */ +public class HashShardMapping extends ShardMapping { + private static class ReverseShardIndexSorter implements Comparator { + public int compare(ShardIndex i1, ShardIndex i2) { + return i2.getBound().compareTo(i1.getBound()); + } + // singleton instance + public static final ReverseShardIndexSorter instance = new ReverseShardIndexSorter(); + } + + private static final MessageDigest md5Hasher; + static { + try { + md5Hasher = MessageDigest.getInstance("MD5"); + } catch(java.security.NoSuchAlgorithmException ex) { + throw new ExceptionInInitializerError(ex); + } + } + + public HashShardMapping(String mappingId, ShardingType shardingType, String globalGroupName, + Set shardTables, Set shardIndices) { + super(mappingId, shardingType, globalGroupName, shardTables, + new TreeSet(ReverseShardIndexSorter.instance)); + this.shardIndices.addAll(shardIndices); + } + + protected ShardIndex getShardIndexForKey(String stringKey) { + String hashedKey = new BigInteger(/* unsigned/positive */1, + md5Hasher.digest(stringKey.getBytes())) + .toString(16).toUpperCase(); + + // pad out to 32 digits + for (int i = 0; i < (32 - hashedKey.length()); ++i) { + hashedKey = "0" + hashedKey; + } + + for (ShardIndex i : this.shardIndices) { + if (i.getBound().compareTo(hashedKey) <= 0) + return i; + } + + // default to the first (highest) bound, + // implementing wrapping + return this.shardIndices.iterator().next(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/RangeShardMapping.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/RangeShardMapping.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/RangeShardMapping.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,71 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/** + * A shard mapping that partitions data by ranges. + */ +public class RangeShardMapping extends ShardMapping { + /** + * A sorter that sorts shard indices from highest to lowest based on the integer + * value of their bounds. For a range shard mapping, the bound is a lowest bound. + */ + private static class RangeShardIndexSorter implements Comparator { + public int compare(ShardIndex i1, ShardIndex i2) { + Integer bound1, bound2; + bound1 = Integer.parseInt(i1.getBound()); + bound2 = Integer.parseInt(i2.getBound()); + return bound2.compareTo(bound1); // this reverses it + } + // singleton instance + public static final RangeShardIndexSorter instance = new RangeShardIndexSorter(); + } + + public RangeShardMapping(String mappingId, ShardingType shardingType, String globalGroupName, + Set shardTables, Set shardIndices) { + // sort shard indices eagerly so {@link getShardIndexForKey} has them in the necessary order + super(mappingId, shardingType, globalGroupName, shardTables, new TreeSet(RangeShardIndexSorter.instance)); + this.shardIndices.addAll(shardIndices); + } + + /** + * Search through the shard indicies to find the shard holding this key. Range-based sharding + * defines a lower bound for each partition with the upper bound being one less than the lower bound + * of the next highest shard. There is no upper bound for the shard with the highest lower bound. + */ + protected ShardIndex getShardIndexForKey(String stringKey) { + Integer key = -1; + key = Integer.parseInt(stringKey); + for (ShardIndex i : this.shardIndices) { + Integer lowerBound = Integer.valueOf(i.getBound()); + if (key >= lowerBound) + return i; + } + return null; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/Response.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/Response.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/Response.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,60 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.List; + +/** + * Response from Fabric request. + */ +public class Response { + private boolean successful; + private Object returnValue; + private String traceString; + + public Response(List responseData) { + this.successful = (Boolean)responseData.get(0); + if (this.successful) { + this.returnValue = responseData.get(2); + } else { + this.traceString = (String)responseData.get(1); + String trace[] = traceString.split("\n"); + // python uses the second from the end of the array + this.returnValue = trace[trace.length-1]; + } + // "details" ignored + } + + public boolean isSuccessful() { + return this.successful; + } + + public Object getReturnValue() { + return this.returnValue; + } + + public String getTraceString() { + return this.traceString; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/Server.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/Server.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/Server.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,102 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +/** + * Database server, as represented by Fabric. + */ +public class Server implements Comparable { + private String groupName; + private String uuid; + private String hostname; + private int port; + private ServerMode mode; + private ServerRole role; + private double weight; + + public Server(String groupName, String uuid, String hostname, int port, + ServerMode mode, ServerRole role, double weight) { + this.groupName = groupName; // may be null + this.uuid = uuid; + this.hostname = hostname; + this.port = port; + this.mode = mode; + this.role = role; + this.weight = weight; + assert(uuid != null && !"".equals(uuid)); + assert(hostname != null && !"".equals(hostname)); + assert(port > 0); + assert(mode != null); + assert(role != null); + assert(weight > 0.0); + } + + public String getGroupName() { + return this.groupName; + } + + public String getUuid() { + return this.uuid; + } + + public String getHostname() { + return this.hostname; + } + + public int getPort() { + return this.port; + } + + public ServerMode getMode() { + return this.mode; + } + + public ServerRole getRole() { + return this.role; + } + + public double getWeight() { + return this.weight; + } + + public String toString() { + return String.format("Server[%s, %s:%d, %s, %s, weight=%s]", + this.uuid, this.hostname, this.port, this.mode, this.role, this.weight); + } + + public boolean equals(Object o) { + if (!(o instanceof Server)) + return false; + Server s = (Server)o; + return s.getUuid().equals(getUuid()); + } + + public int hashCode() { + return getUuid().hashCode(); + } + + public int compareTo(Server other) { + return getUuid().compareTo(other.getUuid()); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerGroup.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerGroup.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerGroup.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,51 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.Set; + +/** + * Server Group - a set of servers responsible for the same set of data + */ +public class ServerGroup { + private String name; + private Set servers; + + public ServerGroup(String name, Set servers) { + this.name = name; + this.servers = servers; + } + + public String getName() { + return this.name; + } + + public Set getServers() { + return this.servers; + } + + public String toString() { + return String.format("Group[name=%s, servers=%s]", this.name, this.servers); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerMode.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerMode.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerMode.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,50 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.HashMap; +import java.util.Map; + +/** + * Server modes. + * From: lib/mysql/fabric/server.py #SERVER MODE CONSTANTS + * and connector-semantics.pdf + */ +public enum ServerMode { + OFFLINE, + READ_ONLY, + READ_WRITE; + + /* Lookup logic from integer constants provided by server. */ + private static final Map serverModesByConstant = new HashMap(); + static { + serverModesByConstant.put(0, OFFLINE); + serverModesByConstant.put(1, READ_ONLY); + serverModesByConstant.put(3, READ_WRITE); + } + + public static ServerMode getFromConstant(Integer constant) { + return serverModesByConstant.get(constant); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerRole.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerRole.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ServerRole.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,50 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.HashMap; +import java.util.Map; + +/** + * Server roles. + */ +public enum ServerRole { + SPARE, + SCALE, + SECONDARY, + PRIMARY; + + /* Lookup logic from integer constants provided by server. */ + private static final Map serverRolesByConstant = new HashMap(); + static { + serverRolesByConstant.put(0, SPARE); + serverRolesByConstant.put(1, SCALE); + serverRolesByConstant.put(2, SECONDARY); + serverRolesByConstant.put(3, PRIMARY); + } + + public static ServerRole getFromConstant(Integer constant) { + return serverRolesByConstant.get(constant); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardIndex.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardIndex.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardIndex.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,62 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +/** + * A shard index represents the physical location of a segment of data. The data segment + * is identified by it's key's relation to the `bound' value. + */ +public class ShardIndex { + private String bound; + private Integer shardId; + private String groupName; + + public ShardIndex(String bound, Integer shardId, String groupName) { + this.bound = bound; + this.shardId = shardId; + this.groupName = groupName; + } + + /** + * The bound that the key will be compared to. This is treated different based on the + * ShardingType. + */ + public String getBound() { + return this.bound; + } + + /** + * A unique identified for this shard. + */ + public Integer getShardId() { + return this.shardId; + } + + /** + * The name of the group in the data for this shard resides. + */ + public String getGroupName() { + return this.groupName; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardMapping.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardMapping.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardMapping.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,94 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.Collections; +import java.util.Set; + +/** + * A shard mapping representing this set of sharded data. + */ +public abstract class ShardMapping { + private String mappingId; + private ShardingType shardingType; + private String globalGroupName; + protected Set shardTables; + protected Set shardIndices; + + public ShardMapping(String mappingId, ShardingType shardingType, String globalGroupName, + Set shardTables, Set shardIndices) { + this.mappingId = mappingId; + this.shardingType = shardingType; + this.globalGroupName = globalGroupName; + this.shardTables = shardTables; + this.shardIndices = shardIndices; + } + + /** + * Lookup the server group that stores the given key. + */ + public String getGroupNameForKey(String key) { + return getShardIndexForKey(key).getGroupName(); + } + + /** + * Decide which shard index stores the given key. + */ + protected abstract ShardIndex getShardIndexForKey(String key); + + /** + * The ID of this mapping. + */ + public String getMappingId() { + return this.mappingId; + } + + /** + * The {@link ShardingType} of this mapping. + */ + public ShardingType getShardingType() { + return this.shardingType; + } + + /** + * The name of the global group for this shard map. + */ + public String getGlobalGroupName() { + return this.globalGroupName; + } + + /** + * Return the set of tables sharded in this mapping. + */ + public Set getShardTables() { + return Collections.unmodifiableSet(this.shardTables); + } + + /** + * Return the set of shards in this mapping. + */ + public Set getShardIndices() { + return Collections.unmodifiableSet(this.shardIndices); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardMappingFactory.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardMappingFactory.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardMappingFactory.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,48 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +import java.util.Set; + +/** + * Factory for creating {@link ShardMapping} objects. This is generally based on the + * {@link ShardingType} but can be modified as necessary. + */ +public class ShardMappingFactory { + public ShardMapping createShardMapping(String mappingId, ShardingType shardingType, String globalGroupName, + Set shardTables, Set shardIndices) { + ShardMapping sm = null; + switch (shardingType) { + case RANGE: + sm = new RangeShardMapping(mappingId, shardingType, globalGroupName, shardTables, shardIndices); + break; + case HASH: + sm = new HashShardMapping(mappingId, shardingType, globalGroupName, shardTables, shardIndices); + break; + default: + throw new IllegalArgumentException("Invalid ShardingType"); + } + return sm; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardTable.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardTable.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardTable.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,60 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +/** + * A shard "table" is a description of how a specific table is distributed across shards. + */ +public class ShardTable { + private String database; + private String table; + private String column; + + public ShardTable(String database, String table, String column) { + this.database = database; + this.table = table; + this.column = column; + } + + /** + * The database in which the sharded data is contained in. + */ + public String getDatabase() { + return this.database; + } + + /** + * The table in which the sharded data is contained in. + */ + public String getTable() { + return this.table; + } + + /** + * The column whose value is used to differentiate between different physical shards. + */ + public String getColumn() { + return this.column; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardingType.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardingType.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/ShardingType.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,36 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric; + +/** + * Sharding type. The algorithm by which rows are distributed across servers. + * @see HashShardMapping + * @see RangeShardMapping + * @see ListShardMapping + */ +public enum ShardingType { + LIST, + RANGE, + HASH; +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/hibernate/FabricMultiTenantConnectionProvider.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/hibernate/FabricMultiTenantConnectionProvider.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/hibernate/FabricMultiTenantConnectionProvider.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,137 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.hibernate; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider; + +import com.mysql.fabric.*; + +/** + * Multi-tenancy connection provider for Hibernate 4. + * + * http://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/service/jdbc/connections/spi/MultiTenantConnectionProvider.html + */ +public class FabricMultiTenantConnectionProvider implements MultiTenantConnectionProvider { + + private static final long serialVersionUID = 1L; + + private FabricConnection fabricConnection; + private String database; + private String table; // the sharded table + private String user; + private String password; + private ShardMapping shardMapping; + private ServerGroup globalGroup; + + public FabricMultiTenantConnectionProvider(String fabricUrl, String database, String table, String user, String password, String fabricUser, String fabricPassword) { + try { + this.fabricConnection = new FabricConnection(fabricUrl, fabricUser, fabricPassword); + this.database = database; + this.table = table; + this.user = user; + this.password = password; + this.shardMapping = this.fabricConnection.getShardMapping(this.database, this.table); + this.globalGroup = this.fabricConnection.getServerGroup(this.shardMapping.getGlobalGroupName()); + } catch(FabricCommunicationException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Find a server with mode READ_WRITE in the given server group and create a JDBC connection to it. + * + * @returns a {@link Connection} to an arbitrary MySQL server + * @throws SQLException if connection fails or a READ_WRITE server is not contained in the group + */ + private Connection getReadWriteConnectionFromServerGroup(ServerGroup serverGroup) throws SQLException { + for (Server s : serverGroup.getServers()) { + if (ServerMode.READ_WRITE.equals(s.getMode())) { + String jdbcUrl = String.format("jdbc:mysql://%s:%s/%s", s.getHostname(), s.getPort(), this.database); + return DriverManager.getConnection(jdbcUrl, this.user, this.password); + } + } + throw new SQLException("Unable to find r/w server for chosen shard mapping in group " + serverGroup.getName()); + } + + /** + * Get a connection that be used to access data or metadata not specific to any shard/tenant. + * The returned connection is a READ_WRITE connection to the global group of the shard mapping + * for the database and table association with this connection provider. + */ + public Connection getAnyConnection() throws SQLException { + return getReadWriteConnectionFromServerGroup(this.globalGroup); + } + + /** + * Get a connection to access data association with the provided `tenantIdentifier' (or shard + * key in Fabric-speak). The returned connection is a READ_WRITE connection. + */ + public Connection getConnection(String tenantIdentifier) throws SQLException { + String serverGroupName = this.shardMapping.getGroupNameForKey(tenantIdentifier); + try { + ServerGroup serverGroup = this.fabricConnection.getServerGroup(serverGroupName); + return getReadWriteConnectionFromServerGroup(serverGroup); + } catch(FabricCommunicationException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Release a non-shard-specific connection. + */ + public void releaseAnyConnection(Connection connection) throws SQLException { + try { + connection.close(); + } catch(Exception ex) { + throw new RuntimeException(ex); + } + } + + /** + * Release a connection specific to `tenantIdentifier'. + */ + public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException { + releaseAnyConnection(connection); + } + + /** + * We don't track connections. + * @returns false + */ + public boolean supportsAggressiveRelease() { + return false; + } + + public boolean isUnwrappableAs(Class unwrapType) { + return false; + } + + public T unwrap(Class unwrapType) { + return null; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/ErrorReportingExceptionInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/ErrorReportingExceptionInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/ErrorReportingExceptionInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,77 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +import com.mysql.fabric.FabricCommunicationException; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.ExceptionInterceptor; +import com.mysql.jdbc.MySQLConnection; +import com.mysql.jdbc.NonRegisteringDriver; +import com.mysql.jdbc.SQLError; + +/** + * Relay the exception to {@link FabricMySQLConnectionProxy} for error + * reporting. + */ +public class ErrorReportingExceptionInterceptor implements ExceptionInterceptor { + private String hostname; + private String port; + private String fabricHaGroup; + + public SQLException interceptException(SQLException sqlEx, Connection conn) { + MySQLConnection mysqlConn = (MySQLConnection) conn; + + // don't intercept exceptions during initialization, before + // the proxy has a chance to setProxy() on the physical + // connection + if (ConnectionImpl.class.isAssignableFrom(mysqlConn.getLoadBalanceSafeProxy().getClass())) { + return null; + } + + FabricMySQLConnectionProxy fabricProxy = (FabricMySQLConnectionProxy) + mysqlConn.getLoadBalanceSafeProxy(); + try { + return fabricProxy.interceptException(sqlEx, conn, this.fabricHaGroup, + this.hostname, this.port); + } catch (FabricCommunicationException ex) { + return SQLError.createSQLException("Failed to report error to Fabric.", + SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, + ex, conn.getExceptionInterceptor(), conn); + } + } + + public void init(Connection conn, Properties props) throws SQLException { + this.hostname = props.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY); + this.port = props.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY); + String connectionAttributes = props.getProperty("connectionAttributes"); + this.fabricHaGroup = connectionAttributes.replaceAll("^.*\\bfabricHaGroup:(.+)\\b.*$", "$1"); + } + + public void destroy() { + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,101 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.sql.SQLException; +import java.util.Set; +import com.mysql.fabric.ServerGroup; + +/** + * + */ +public interface FabricMySQLConnection extends com.mysql.jdbc.MySQLConnection { + /** + * Clear all the state that is used to determine which server to + * send queries to. + */ + void clearServerSelectionCriteria() throws SQLException; + + /** + * Set the shard key for the data being accessed. + */ + void setShardKey(String shardKey) throws SQLException; + + /** + * Get the shard key for the data being accessed. + */ + String getShardKey(); + + /** + * Set the table being accessed. Can be a table name or a + * "database.table" pair. The table must be known by Fabric + * as a sharded table. + */ + void setShardTable(String shardTable) throws SQLException; + + /** + * Get the table being accessed. + */ + String getShardTable(); + + /** + * Set the server group name to connect to. Direct server group selection + * is mutually exclusive of sharded data access. + */ + void setServerGroupName(String serverGroupName) throws SQLException; + + /** + * Get the server group name when using direct server group selection. + */ + String getServerGroupName(); + + /** + * Get the current server group. + * @returns The currently chosen group if sufficient server group selection + * criteria has been provided. Otherwise null. + */ + ServerGroup getCurrentServerGroup(); + + /** + * Clear the list of tables for the last query. This also clears the + * shard mapping/table and must be given again for the next query via + * {@link setShardTable} or {@addQueryTable}. + */ + void clearQueryTables() throws SQLException; + + /** + * Add a table to the set of tables used for the next query on this connection. + * This is used for: + *
    + *
  • Choosing a shard given the tables used
  • + *
  • Preventing cross-shard queries
  • + *
+ */ + void addQueryTable(String tableName) throws SQLException; + + /** + * The set of tables to be used in the next query on this connection. + */ + Set getQueryTables(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnectionProperties.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnectionProperties.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnectionProperties.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,52 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import com.mysql.jdbc.ConnectionProperties; + +/** + * Additional properties for {@link FabricMySQLConnection}s. + */ +public interface FabricMySQLConnectionProperties extends ConnectionProperties { + void setFabricShardKey(String value); + String getFabricShardKey(); + + void setFabricShardTable(String value); + String getFabricShardTable(); + + void setFabricServerGroup(String value); + String getFabricServerGroup(); + + void setFabricProtocol(String value); + String getFabricProtocol(); + + void setFabricUsername(String value); + String getFabricUsername(); + + void setFabricPassword(String value); + String getFabricPassword(); + + void setFabricReportErrors(boolean value); + boolean getFabricReportErrors(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnectionProxy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnectionProxy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLConnectionProxy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,2804 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.sql.CallableStatement; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Savepoint; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TimeZone; +import java.util.Timer; +import java.util.concurrent.Executor; + +import com.mysql.fabric.FabricCommunicationException; +import com.mysql.fabric.FabricConnection; +import com.mysql.fabric.Server; +import com.mysql.fabric.ServerGroup; +import com.mysql.fabric.ServerMode; +import com.mysql.fabric.ShardMapping; +import com.mysql.jdbc.Buffer; +import com.mysql.jdbc.CachedResultSetMetaData; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ConnectionProperties; +import com.mysql.jdbc.ConnectionPropertiesImpl; +import com.mysql.jdbc.ExceptionInterceptor; +import com.mysql.jdbc.Extension; +import com.mysql.jdbc.Field; +import com.mysql.jdbc.LoadBalancingConnectionProxy; +import com.mysql.jdbc.MySQLConnection; +import com.mysql.jdbc.MysqlIO; +import com.mysql.jdbc.NonRegisteringDriver; +import com.mysql.jdbc.ReplicationConnection; +import com.mysql.jdbc.ResultSetInternalMethods; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.ServerPreparedStatement; +import com.mysql.jdbc.SingleByteCharsetConverter; +import com.mysql.jdbc.StatementImpl; +import com.mysql.jdbc.StatementInterceptorV2; +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.profiler.ProfilerEventHandler; + +/** + * A proxy to a set of MySQL servers managed by MySQL Fabric. + * + * Limitations: + *
    + *
  • One shard key can be specified
  • + *
+ */ +public class FabricMySQLConnectionProxy extends ConnectionPropertiesImpl + implements FabricMySQLConnection, FabricMySQLConnectionProperties { + + private static final long serialVersionUID = 1L; + + protected FabricConnection fabricConnection; + + protected boolean closed = false; + + protected boolean transactionInProgress = false; + + // Set of connections created for this proxy (initialized lazily) + protected Map serverConnections = + new HashMap(); + + // Connection currently in use for this proxy + protected ReplicationConnection currentConnection; + + // Server selection criteria + // one for group selection (i.e. sharding), + // one for server selection (i.e. RO, global, load balancing, etc) + protected String shardKey; + protected String shardTable; + protected String serverGroupName; + + protected Set queryTables = new HashSet(); + + protected Server server; + protected ServerGroup serverGroup; + + protected String host; + protected String port; + protected String username; + protected String password; + protected String database; + + protected ShardMapping shardMapping; + + protected boolean readOnly = false; + protected boolean autoCommit = true; + protected int transactionIsolation = Connection.TRANSACTION_REPEATABLE_READ; + + private String fabricShardKey; + private String fabricShardTable; + private String fabricServerGroup; + private String fabricProtocol; + private String fabricUsername; + private String fabricPassword; + private boolean reportErrors = false; + + public FabricMySQLConnectionProxy(Properties props) throws SQLException { + // first, handle and remove Fabric-specific properties. once + // fabricShardKey et al are ConnectionProperty instances this + // will be unnecessary + this.fabricShardKey = props.getProperty(FabricMySQLDriver.FABRIC_SHARD_KEY_PROPERTY_KEY); + this.fabricShardTable = props.getProperty(FabricMySQLDriver.FABRIC_SHARD_TABLE_PROPERTY_KEY); + this.fabricServerGroup = props.getProperty(FabricMySQLDriver.FABRIC_SERVER_GROUP_PROPERTY_KEY); + this.fabricProtocol = props.getProperty(FabricMySQLDriver.FABRIC_PROTOCOL_PROPERTY_KEY); + this.fabricUsername = props.getProperty(FabricMySQLDriver.FABRIC_USERNAME_PROPERTY_KEY); + this.fabricPassword = props.getProperty(FabricMySQLDriver.FABRIC_PASSWORD_PROPERTY_KEY); + this.reportErrors = Boolean.valueOf(props.getProperty(FabricMySQLDriver.FABRIC_REPORT_ERRORS_PROPERTY_KEY)); + props.remove(FabricMySQLDriver.FABRIC_SHARD_KEY_PROPERTY_KEY); + props.remove(FabricMySQLDriver.FABRIC_SHARD_TABLE_PROPERTY_KEY); + props.remove(FabricMySQLDriver.FABRIC_SERVER_GROUP_PROPERTY_KEY); + props.remove(FabricMySQLDriver.FABRIC_PROTOCOL_PROPERTY_KEY); + props.remove(FabricMySQLDriver.FABRIC_USERNAME_PROPERTY_KEY); + props.remove(FabricMySQLDriver.FABRIC_PASSWORD_PROPERTY_KEY); + props.remove(FabricMySQLDriver.FABRIC_REPORT_ERRORS_PROPERTY_KEY); + + this.host = props.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY); + this.port = props.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY); + this.username = props.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY); + this.password = props.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY); + this.database = props.getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY); + if (this.username == null) { + this.username = ""; + } + if (this.password == null) { + this.password = ""; + } + + String exceptionInterceptors = props.getProperty("exceptionInterceptors"); + if (exceptionInterceptors == null || "null".equals("exceptionInterceptors")) { + exceptionInterceptors = ""; + } else { + exceptionInterceptors += ","; + } + exceptionInterceptors += "com.mysql.fabric.jdbc.ErrorReportingExceptionInterceptor"; + props.setProperty("exceptionInterceptors", exceptionInterceptors); + + initializeProperties(props); + + // validation check of properties + if (this.fabricServerGroup != null && + this.fabricShardTable != null) { + throw SQLError.createSQLException("Server group and shard table are mutually exclusive. Only one may be provided.", + SQLError.SQL_STATE_CONNECTION_REJECTED, + null, + getExceptionInterceptor(), + this); + } + + try { + String url = this.fabricProtocol + "://" + this.host + ":" + this.port; + this.fabricConnection = new FabricConnection(url, this.fabricUsername, this.fabricPassword); + } catch(FabricCommunicationException ex) { + throw SQLError.createSQLException("Unable to establish connection to the Fabric server", + SQLError.SQL_STATE_CONNECTION_REJECTED, + ex, + getExceptionInterceptor(), + this); + } + + setShardTable(this.fabricShardTable); + setShardKey(this.fabricShardKey); + + setServerGroupName(this.fabricServerGroup); + } + + private boolean intercepting = false; // prevent recursion + + /** + * + * @param sqlEx + * @param conn + * @param group + * @param hostname + * @param portnumber + * @return + * @throws FabricCommunicationException + */ + SQLException interceptException(SQLException sqlEx, Connection conn, + String group, String hostname, String portnumber) + throws FabricCommunicationException { + if (!sqlEx.getSQLState().startsWith("08")) { + return null; + } + + if (intercepting) { + return null; + } + + intercepting = true; + + try { + // find the Server corresponding to this connection + // TODO could be indexed for quicker lookup + Server currentServer = null; + ServerGroup currentGroup = this.fabricConnection.getServerGroup(group); + for (Server s : currentGroup.getServers()) { + if (s.getHostname().equals(hostname) && + Integer.valueOf(s.getPort()).toString().equals(portnumber)) { + currentServer = s; + break; + } + } + + if (currentServer == null) { + return SQLError.createSQLException("Unable to lookup server to report error to Fabric", + sqlEx.getSQLState(), sqlEx, getExceptionInterceptor(), this); + } + + if (this.reportErrors) { + this.fabricConnection.getClient().reportServerError(currentServer, + sqlEx.toString(), true); + } + + this.serverConnections.remove(this.serverGroup); + try { + this.currentConnection.close(); + } catch (SQLException ex) { + } + this.currentConnection = null; + this.serverGroup = currentGroup; + } finally { + intercepting = false; + } + + return null; + } + + ///////////////////////////////////////// + // Server selection criteria and logic // + ///////////////////////////////////////// + public void setShardKey(String shardKey) throws SQLException { + ensureNoTransactionInProgress(); + + this.currentConnection = null; + + if (shardKey != null) { + if (this.serverGroupName != null) { + throw SQLError.createSQLException("Shard key cannot be provided when server group is chosen directly.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + null, + getExceptionInterceptor(), + this); + } else if (this.shardTable == null) { + throw SQLError.createSQLException("Shard key cannot be provided with a shard table.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + null, + getExceptionInterceptor(), + this); + } + + this.server = null; + // sharded group selection + setCurrentServerGroup(this.shardMapping.getGroupNameForKey(shardKey)); + } else if (this.shardTable != null) { + setCurrentServerGroup(this.shardMapping.getGlobalGroupName()); + } + this.shardKey = shardKey; + } + + public String getShardKey() { + return this.shardKey; + } + + public void setShardTable(String shardTable) throws SQLException { + ensureNoTransactionInProgress(); + + this.currentConnection = null; + + if (this.serverGroupName != null) { + throw SQLError.createSQLException("Server group and shard table are mutually exclusive. Only one may be provided.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + null, + getExceptionInterceptor(), + this); + } + + this.server = null; + this.shardKey = null; + this.serverGroup = null; + this.shardTable = shardTable; + if (shardTable == null) { + this.shardMapping = null; + } else { + // lookup shard mapping + String table = shardTable; + String db = this.database; + if (shardTable.contains(".")) { + String pair[] = shardTable.split("\\."); + table = pair[0]; + db = pair[1]; + } + try { + this.shardMapping = this.fabricConnection.getShardMapping(db, table); + if (this.shardMapping == null) { + throw SQLError.createSQLException("Shard mapping not found for table `" + shardTable + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + null, + getExceptionInterceptor(), + this); + } + // default to global group + setCurrentServerGroup(this.shardMapping.getGlobalGroupName()); + + } catch(FabricCommunicationException ex) { + throw SQLError.createSQLException("Fabric communication failure.", + SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, + ex, + getExceptionInterceptor(), + this); + } + } + } + + public String getShardTable() { + return this.shardTable; + } + + public void setServerGroupName(String serverGroupName) throws SQLException { + ensureNoTransactionInProgress(); + + this.currentConnection = null; + + // direct group selection + if (serverGroupName != null) { + setCurrentServerGroup(serverGroupName); + } + + this.serverGroupName = serverGroupName; + } + + public String getServerGroupName() { + return this.serverGroupName; + } + + public void clearServerSelectionCriteria() throws SQLException { + ensureNoTransactionInProgress(); + this.shardTable = null; + this.shardKey = null; + this.serverGroupName = null; + this.server = null; + this.serverGroup = null; + this.queryTables.clear(); + this.currentConnection = null; + } + + public ServerGroup getCurrentServerGroup() { + return this.serverGroup; + } + + public void clearQueryTables() throws SQLException { + ensureNoTransactionInProgress(); + + this.currentConnection = null; + + this.queryTables.clear(); + setShardTable(null); + } + + /** + * Add a table to the set of tables used for the next query on this connection. + * This is used for: + *
    + *
  • Choosing a shard given the tables used
  • + *
  • Preventing cross-shard queries
  • + *
+ */ + public void addQueryTable(String tableName) throws SQLException { + ensureNoTransactionInProgress(); + + this.currentConnection = null; + + try { + // choose shard mapping if necessary + if (this.shardMapping == null) { + if (this.fabricConnection.getShardMapping(this.database, tableName) != null) { + setShardTable(tableName); + } + } else { // make sure we aren't in conflict with the chosen shard mapping + ShardMapping mappingForTableName = this.fabricConnection.getShardMapping(this.database, tableName); + if (mappingForTableName != null && + !mappingForTableName.equals(this.shardMapping)) + throw SQLError.createSQLException("Cross-shard query not allowed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + null, + getExceptionInterceptor(), + this); + } + this.queryTables.add(tableName); + } catch(FabricCommunicationException ex) { + throw SQLError.createSQLException("Fabric communication failure.", + SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, + ex, + getExceptionInterceptor(), + this); + } + } + + /** + * The set of tables to be used in the next query on this connection. + */ + public Set getQueryTables() { + return this.queryTables; + } + + /** + * Change the server group to the given named group. + */ + protected void setCurrentServerGroup(String serverGroupName) throws SQLException { + this.server = null; + this.serverGroup = null; + + try { + this.serverGroup = this.fabricConnection.getServerGroup(serverGroupName); + } catch(FabricCommunicationException ex) { + throw SQLError.createSQLException("Fabric communication failure.", + SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, + ex, + getExceptionInterceptor(), + this); + } + + if (this.serverGroup == null) { + throw SQLError.createSQLException("Cannot find server group: `" + serverGroupName + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + null, + getExceptionInterceptor(), + this); + } + } + + ////////////////////////////////////////////////////// + // Methods dealing with state internal to the proxy // + ////////////////////////////////////////////////////// + /** + * Get the active connection as an object implementing the + * internal MySQLConnection interface. This should not be used + * unless a MySQLConnection is required. + * + * {@link getActiveConnection()} is provided for the general case. + * The returned object is not a {@link ReplicationConnection}, but + * instead the {@link LoadBalancingConnectionProxy} for either the + * master or slaves. + */ + protected MySQLConnection getActiveMySQLConnection() throws SQLException { + ReplicationConnection c = (ReplicationConnection) getActiveConnection(); + MySQLConnection mc = (MySQLConnection) c.getCurrentConnection(); + return mc; + } + + protected MySQLConnection getActiveMySQLConnectionPassive() { + try { + return getActiveMySQLConnection(); + } catch (SQLException ex) { + throw new IllegalStateException("Unable to determine active connection", ex); + } + } + + protected Connection getActiveConnectionPassive() { + try { + return getActiveConnection(); + } catch (SQLException ex) { + throw new IllegalStateException("Unable to determine active connection", ex); + } + } + + protected Connection getActiveConnection() throws SQLException { + if (this.currentConnection != null) { + return this.currentConnection; + } + + if (getCurrentServerGroup() == null) { + throw SQLError.createSQLException("No server group selected.", + SQLError.SQL_STATE_CONNECTION_REJECTED, + null, + getExceptionInterceptor(), + this); + } + + // try to find an existing replication connection to the current group + this.currentConnection = this.serverConnections.get(this.serverGroup); + if (this.currentConnection != null) { + return this.currentConnection; + } + + // otherwise, build a replication connection to the current group + List masterHost = new ArrayList(); + List slaveHosts = new ArrayList(); + for (Server s : this.serverGroup.getServers()) { + if (ServerMode.READ_WRITE.equals(s.getMode())) { + masterHost.add(s.getHostname() + ":" + s.getPort()); + } else { + slaveHosts.add(s.getHostname() + ":" + s.getPort()); + } + } + Properties info = exposeAsProperties(null); + info.put("replicationConnectionGroup", this.serverGroup.getName()); + info.setProperty(NonRegisteringDriver.USER_PROPERTY_KEY, this.username); + info.setProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY, this.password); + info.setProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY, getCatalog()); + info.setProperty("connectionAttributes", "fabricHaGroup:" + this.serverGroup.getName()); + this.currentConnection = new ReplicationConnection(info, info, masterHost, slaveHosts); + this.serverConnections.put(this.serverGroup, this.currentConnection); + + this.currentConnection.setProxy(this); + this.currentConnection.setAutoCommit(this.autoCommit); + this.currentConnection.setReadOnly(this.readOnly); + this.currentConnection.setTransactionIsolation(this.transactionIsolation); + return this.currentConnection; + } + + private void ensureOpen() throws SQLException { + if (this.closed) { + throw SQLError.createSQLException("No operations allowed after connection closed.", + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, + getExceptionInterceptor()); + } + } + + private void ensureNoTransactionInProgress() throws SQLException { + ensureOpen(); + if (this.transactionInProgress && !this.autoCommit) { + throw SQLError.createSQLException("Not allow while a transaction is active.", + "25000", getExceptionInterceptor()); + } + } + + /** + * Close this connection proxy which entails closing all + * open connections to MySQL servers. + */ + public void close() throws SQLException { + this.closed = true; + for (Connection c : this.serverConnections.values()) { + try { + c.close(); + } catch(SQLException ex) { + } + } + } + + public boolean isClosed() { + return this.closed; + } + + /** + * + * @param timeout + * @return + * @throws SQLException + */ + public boolean isValid(int timeout) throws SQLException { + return !this.closed; + } + + public void setReadOnly(boolean readOnly) throws SQLException { + this.readOnly = readOnly; + for (ReplicationConnection conn : serverConnections.values()) { + conn.setReadOnly(readOnly); + } + } + + public boolean isReadOnly() throws SQLException { + return this.readOnly; + } + + public boolean isReadOnly(boolean useSessionStatus) throws SQLException { + return this.readOnly; + } + + public void setCatalog(String catalog) throws SQLException { + this.database = catalog; + for (Connection c : serverConnections.values()) { + c.setCatalog(catalog); + } + } + + public String getCatalog() { + return this.database; + } + + public void rollback() throws SQLException { + getActiveConnection().rollback(); + transactionCompleted(); + } + + public void rollback(Savepoint savepoint) throws SQLException { + getActiveConnection().rollback(); + transactionCompleted(); + } + + public void commit() throws SQLException { + getActiveConnection().commit(); + transactionCompleted(); + } + + public void setAutoCommit(boolean autoCommit) throws SQLException { + this.autoCommit = autoCommit; + for (Connection c : serverConnections.values()) { + c.setAutoCommit(this.autoCommit); + } + } + + public void transactionBegun() throws SQLException { + if (!this.autoCommit) { + this.transactionInProgress = true; + } + } + + public void transactionCompleted() throws SQLException { + this.transactionInProgress = false; + } + + public boolean getAutoCommit() { + return this.autoCommit; + } + + public MySQLConnection getLoadBalanceSafeProxy() { + return getActiveMySQLConnectionPassive(); + } + + //////////////////////////////////////////////////////// + // Methods applying changes to all active connections // + //////////////////////////////////////////////////////// + public void setTransactionIsolation(int level) throws SQLException { + this.transactionIsolation = level; + for (Connection c : serverConnections.values()) { + c.setTransactionIsolation(level); + } + } + + public void setTypeMap(Map> map) throws SQLException { + for (Connection c : serverConnections.values()) { + c.setTypeMap(map); + } + } + + public void setHoldability(int holdability) throws SQLException { + for (Connection c : serverConnections.values()) { + c.setHoldability(holdability); + } + } + + public void setProxy(MySQLConnection proxy) { + } + + ////////////////////////////////////////////////////////// + // Methods delegating directly to the active connection // + ////////////////////////////////////////////////////////// + public Savepoint setSavepoint() throws SQLException { + return getActiveConnection().setSavepoint(); + } + + public Savepoint setSavepoint(String name) throws SQLException { + transactionInProgress = true; + return getActiveConnection().setSavepoint(name); + } + + public void releaseSavepoint(Savepoint savepoint) { + } + + public CallableStatement prepareCall(String sql) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareCall(sql); + } + + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + transactionBegun(); + return getActiveConnection().prepareCall(sql, resultSetType, resultSetConcurrency); + } + + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public PreparedStatement prepareStatement(String sql) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareStatement(sql); + } + + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareStatement(sql, autoGeneratedKeys); + } + + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareStatement(sql, columnIndexes); + } + + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + transactionBegun(); + return getActiveConnection().prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + transactionBegun(); + return getActiveConnection().prepareStatement(sql, columnNames); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql) + throws SQLException { + transactionBegun(); + return getActiveConnection().clientPrepareStatement(sql); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + transactionBegun(); + return getActiveConnection().clientPrepareStatement(sql, autoGenKeyIndex); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + transactionBegun(); + return getActiveConnection().clientPrepareStatement(sql, resultSetType, resultSetConcurrency); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + transactionBegun(); + return getActiveConnection().clientPrepareStatement(sql, autoGenKeyIndexes); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + transactionBegun(); + return getActiveConnection().clientPrepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + transactionBegun(); + return getActiveConnection().clientPrepareStatement(sql, autoGenKeyColNames); + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql) + throws SQLException { + transactionBegun(); + return getActiveConnection().serverPrepareStatement(sql); + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + transactionBegun(); + return getActiveConnection().serverPrepareStatement(sql, autoGenKeyIndex); + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + transactionBegun(); + return getActiveConnection().serverPrepareStatement(sql, resultSetType, resultSetConcurrency); + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + transactionBegun(); + return getActiveConnection().serverPrepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + transactionBegun(); + return getActiveConnection().serverPrepareStatement(sql, autoGenKeyIndexes); + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + transactionBegun(); + return getActiveConnection().serverPrepareStatement(sql, autoGenKeyColNames); + } + + public Statement createStatement() throws SQLException { + transactionBegun(); + return getActiveConnection().createStatement(); + } + + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + transactionBegun(); + return getActiveConnection().createStatement(resultSetType, resultSetConcurrency); + } + + public Statement createStatement(int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + transactionBegun(); + return getActiveConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public ResultSetInternalMethods execSQL(StatementImpl callingStatement, + String sql, int maxRows, Buffer packet, int resultSetType, + int resultSetConcurrency, boolean streamResults, String catalog, + Field[] cachedMetadata) throws SQLException { + return getActiveMySQLConnection().execSQL(callingStatement, sql, maxRows, packet, resultSetType, + resultSetConcurrency, streamResults, catalog, cachedMetadata); + } + + public ResultSetInternalMethods execSQL(StatementImpl callingStatement, + String sql, int maxRows, Buffer packet, int resultSetType, + int resultSetConcurrency, boolean streamResults, String catalog, + Field[] cachedMetadata, boolean isBatch) throws SQLException { + return getActiveMySQLConnection().execSQL(callingStatement, sql, maxRows, packet, resultSetType, + resultSetConcurrency, streamResults, catalog, cachedMetadata, isBatch); + } + + public String extractSqlFromPacket(String possibleSqlQuery, Buffer queryPacket, + int endOfQueryPacketPosition) throws SQLException { + return getActiveMySQLConnection().extractSqlFromPacket(possibleSqlQuery, queryPacket, endOfQueryPacketPosition); + } + + public StringBuffer generateConnectionCommentBlock(StringBuffer buf) { + return getActiveMySQLConnectionPassive().generateConnectionCommentBlock(buf); + } + + public MysqlIO getIO() throws SQLException { + return getActiveMySQLConnection().getIO(); + } + + /** + * Only valid until the end of the transaction. These could optionally be implemented + * to only return true if all current connections return true. + */ + public boolean versionMeetsMinimum(int major, int minor, + int subminor) throws SQLException { + return getActiveConnection().versionMeetsMinimum(major, minor, subminor); + } + + /** + * Only valid until the end of the transaction. + */ + public boolean supportsIsolationLevel() { + return getActiveConnectionPassive().supportsIsolationLevel(); + } + + /** + * Only valid until the end of the transaction. + */ + public boolean supportsQuotedIdentifiers() { + return getActiveConnectionPassive().supportsQuotedIdentifiers(); + } + + public DatabaseMetaData getMetaData() throws SQLException { + return getActiveConnection().getMetaData(); + } + + /** + * Methods doing essentially nothing + * @param iface + * @return + */ + public boolean isWrapperFor(Class iface) { + return false; + } + + /** + * + * @param iface + * @return + */ + public T unwrap(Class iface) { + return null; + } + + public void unSafeStatementInterceptors() throws SQLException { + } + + public boolean supportsTransactions() { + // Fabric requires MySQL 5.6 w/GTID + return true; + } + + public boolean isRunningOnJDK13() { + return false; + } + + public void createNewIO(boolean isForReconnect) throws SQLException { + throw SQLError.notImplemented(); + } + + public void dumpTestcaseQuery(String query) { + // no-op + } + + public void abortInternal() throws SQLException { + // no-op + } + + public boolean isServerLocal() throws SQLException { + // Fabric doesn't support pipes + return false; + } + + public void shutdownServer() throws SQLException { + throw SQLError.notImplemented(); + } + + public void clearHasTriedMaster() { + // no-op + } + + public boolean hasTriedMaster() { + return false; + } + + // This proxy is not XA-aware + public boolean isInGlobalTx() { + return false; + } + + // This proxy is not XA-aware + public void setInGlobalTx(boolean flag) { + throw new RuntimeException("Global transactions not supported."); + } + + public void changeUser(String userName, String newPassword) + throws SQLException { + throw SQLError.createSQLException("User change not allowed.", + getExceptionInterceptor()); + } + + ///////////////////////////////////// + // FabricMySQLConnectionProperties // + ///////////////////////////////////// + public void setFabricShardKey(String value) { + this.fabricShardKey = value; + } + + public String getFabricShardKey() { + return this.fabricShardKey; + } + + public void setFabricShardTable(String value) { + this.fabricShardTable = value; + } + + public String getFabricShardTable() { + return this.fabricShardTable; + } + + public void setFabricServerGroup(String value) { + this.fabricServerGroup = value; + } + + public String getFabricServerGroup() { + return this.fabricServerGroup; + } + + public void setFabricProtocol(String value) { + this.fabricProtocol = value; + } + + public String getFabricProtocol() { + return this.fabricProtocol; + } + + public void setFabricUsername(String value) { + this.fabricUsername = value; + } + + public String getFabricUsername() { + return this.fabricUsername; + } + + public void setFabricPassword(String value) { + this.fabricPassword = value; + } + + public String getFabricPassword() { + return this.fabricPassword; + } + + public void setFabricReportErrors(boolean value) { + this.reportErrors = value; + } + + public boolean getFabricReportErrors() { + return this.reportErrors; + } + + /////////////////////////////////////////////////////// + // ConnectionProperties - applied to all connections // + /////////////////////////////////////////////////////// + public void setAllowLoadLocalInfile(boolean property) { + super.setAllowLoadLocalInfile(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAllowLoadLocalInfile(property); + } + } + + public void setAllowMultiQueries(boolean property) { + super.setAllowMultiQueries(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAllowMultiQueries(property); + } + } + + public void setAllowNanAndInf(boolean flag) { + super.setAllowNanAndInf(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAllowNanAndInf(flag); + } + } + + public void setAllowUrlInLocalInfile(boolean flag) { + super.setAllowUrlInLocalInfile(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAllowUrlInLocalInfile(flag); + } + } + + public void setAlwaysSendSetIsolation(boolean flag) { + super.setAlwaysSendSetIsolation(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAlwaysSendSetIsolation(flag); + } + } + + public void setAutoDeserialize(boolean flag) { + super.setAutoDeserialize(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoDeserialize(flag); + } + } + + public void setAutoGenerateTestcaseScript(boolean flag) { + super.setAutoGenerateTestcaseScript(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoGenerateTestcaseScript(flag); + } + } + + public void setAutoReconnect(boolean flag) { + super.setAutoReconnect(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoReconnect(flag); + } + } + + public void setAutoReconnectForConnectionPools(boolean property) { + super.setAutoReconnectForConnectionPools(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoReconnectForConnectionPools(property); + } + } + + public void setAutoReconnectForPools(boolean flag) { + super.setAutoReconnectForPools(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoReconnectForPools(flag); + } + } + + public void setBlobSendChunkSize(String value) throws SQLException { + super.setBlobSendChunkSize(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setBlobSendChunkSize(value); + } + } + + public void setCacheCallableStatements(boolean flag) { + super.setCacheCallableStatements(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCacheCallableStatements(flag); + } + } + + public void setCachePreparedStatements(boolean flag) { + super.setCachePreparedStatements(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCachePreparedStatements(flag); + } + } + + public void setCacheResultSetMetadata(boolean property) { + super.setCacheResultSetMetadata(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCacheResultSetMetadata(property); + } + } + + public void setCacheServerConfiguration(boolean flag) { + super.setCacheServerConfiguration(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCacheServerConfiguration(flag); + } + } + + public void setCallableStatementCacheSize(int size) throws SQLException { + super.setCallableStatementCacheSize(size); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCallableStatementCacheSize(size); + } + } + + public void setCapitalizeDBMDTypes(boolean property) { + super.setCapitalizeDBMDTypes(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCapitalizeDBMDTypes(property); + } + } + + public void setCapitalizeTypeNames(boolean flag) { + super.setCapitalizeTypeNames(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCapitalizeTypeNames(flag); + } + } + + public void setCharacterEncoding(String encoding) { + super.setCharacterEncoding(encoding); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCharacterEncoding(encoding); + } + } + + public void setCharacterSetResults(String characterSet) { + super.setCharacterSetResults(characterSet); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCharacterSetResults(characterSet); + } + } + + public void setClobberStreamingResults(boolean flag) { + super.setClobberStreamingResults(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setClobberStreamingResults(flag); + } + } + + public void setClobCharacterEncoding(String encoding) { + super.setClobCharacterEncoding(encoding); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setClobCharacterEncoding(encoding); + } + } + + public void setConnectionCollation(String collation) { + super.setConnectionCollation(collation); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setConnectionCollation(collation); + } + } + + public void setConnectTimeout(int timeoutMs) throws SQLException { + super.setConnectTimeout(timeoutMs); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setConnectTimeout(timeoutMs); + } + } + + public void setContinueBatchOnError(boolean property) { + super.setContinueBatchOnError(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setContinueBatchOnError(property); + } + } + + public void setCreateDatabaseIfNotExist(boolean flag) { + super.setCreateDatabaseIfNotExist(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCreateDatabaseIfNotExist(flag); + } + } + + public void setDefaultFetchSize(int n) throws SQLException { + super.setDefaultFetchSize(n); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDefaultFetchSize(n); + } + } + + public void setDetectServerPreparedStmts(boolean property) { + super.setDetectServerPreparedStmts(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDetectServerPreparedStmts(property); + } + } + + public void setDontTrackOpenResources(boolean flag) { + super.setDontTrackOpenResources(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDontTrackOpenResources(flag); + } + } + + public void setDumpQueriesOnException(boolean flag) { + super.setDumpQueriesOnException(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDumpQueriesOnException(flag); + } + } + + public void setDynamicCalendars(boolean flag) { + super.setDynamicCalendars(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDynamicCalendars(flag); + } + } + + public void setElideSetAutoCommits(boolean flag) { + super.setElideSetAutoCommits(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setElideSetAutoCommits(flag); + } + } + + public void setEmptyStringsConvertToZero(boolean flag) { + super.setEmptyStringsConvertToZero(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setEmptyStringsConvertToZero(flag); + } + } + + public void setEmulateLocators(boolean property) { + super.setEmulateLocators(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setEmulateLocators(property); + } + } + + public void setEmulateUnsupportedPstmts(boolean flag) { + super.setEmulateUnsupportedPstmts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setEmulateUnsupportedPstmts(flag); + } + } + + public void setEnablePacketDebug(boolean flag) { + super.setEnablePacketDebug(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setEnablePacketDebug(flag); + } + } + + public void setEncoding(String property) { + super.setEncoding(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setEncoding(property); + } + } + + public void setExplainSlowQueries(boolean flag) { + super.setExplainSlowQueries(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setExplainSlowQueries(flag); + } + } + + public void setFailOverReadOnly(boolean flag) { + super.setFailOverReadOnly(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setFailOverReadOnly(flag); + } + } + + public void setGatherPerformanceMetrics(boolean flag) { + super.setGatherPerformanceMetrics(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setGatherPerformanceMetrics(flag); + } + } + + public void setHoldResultsOpenOverStatementClose(boolean flag) { + super.setHoldResultsOpenOverStatementClose(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setHoldResultsOpenOverStatementClose(flag); + } + } + + public void setIgnoreNonTxTables(boolean property) { + super.setIgnoreNonTxTables(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setIgnoreNonTxTables(property); + } + } + + public void setInitialTimeout(int property) throws SQLException { + super.setInitialTimeout(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setInitialTimeout(property); + } + } + + public void setIsInteractiveClient(boolean property) { + super.setIsInteractiveClient(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setIsInteractiveClient(property); + } + } + + public void setJdbcCompliantTruncation(boolean flag) { + super.setJdbcCompliantTruncation(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setJdbcCompliantTruncation(flag); + } + } + + public void setLocatorFetchBufferSize(String value) + throws SQLException { + super.setLocatorFetchBufferSize(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLocatorFetchBufferSize(value); + } + } + + public void setLogger(String property) { + super.setLogger(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLogger(property); + } + } + + public void setLoggerClassName(String className) { + super.setLoggerClassName(className); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoggerClassName(className); + } + } + + public void setLogSlowQueries(boolean flag) { + super.setLogSlowQueries(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLogSlowQueries(flag); + } + } + + public void setMaintainTimeStats(boolean flag) { + super.setMaintainTimeStats(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setMaintainTimeStats(flag); + } + } + + public void setMaxQuerySizeToLog(int sizeInBytes) throws SQLException { + super.setMaxQuerySizeToLog(sizeInBytes); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setMaxQuerySizeToLog(sizeInBytes); + } + } + + public void setMaxReconnects(int property) throws SQLException { + super.setMaxReconnects(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setMaxReconnects(property); + } + } + + public void setMaxRows(int property) throws SQLException { + super.setMaxRows(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setMaxRows(property); + } + } + + public void setMetadataCacheSize(int value) throws SQLException { + super.setMetadataCacheSize(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setMetadataCacheSize(value); + } + } + + public void setNoDatetimeStringSync(boolean flag) { + super.setNoDatetimeStringSync(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setNoDatetimeStringSync(flag); + } + } + + public void setNullCatalogMeansCurrent(boolean value) { + super.setNullCatalogMeansCurrent(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setNullCatalogMeansCurrent(value); + } + } + + public void setNullNamePatternMatchesAll(boolean value) { + super.setNullNamePatternMatchesAll(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setNullNamePatternMatchesAll(value); + } + } + + public void setPacketDebugBufferSize(int size) throws SQLException { + super.setPacketDebugBufferSize(size); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPacketDebugBufferSize(size); + } + } + + public void setParanoid(boolean property) { + super.setParanoid(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setParanoid(property); + } + } + + public void setPedantic(boolean property) { + super.setPedantic(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPedantic(property); + } + } + + public void setPreparedStatementCacheSize(int cacheSize) throws SQLException { + super.setPreparedStatementCacheSize(cacheSize); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPreparedStatementCacheSize(cacheSize); + } + } + + public void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) throws SQLException { + super.setPreparedStatementCacheSqlLimit(cacheSqlLimit); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPreparedStatementCacheSqlLimit(cacheSqlLimit); + } + } + + public void setProfileSql(boolean property) { + super.setProfileSql(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setProfileSql(property); + } + } + + public void setProfileSQL(boolean flag) { + super.setProfileSQL(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setProfileSQL(flag); + } + } + + public void setPropertiesTransform(String value) { + super.setPropertiesTransform(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPropertiesTransform(value); + } + } + + public void setQueriesBeforeRetryMaster(int property) throws SQLException { + super.setQueriesBeforeRetryMaster(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setQueriesBeforeRetryMaster(property); + } + } + + public void setReconnectAtTxEnd(boolean property) { + super.setReconnectAtTxEnd(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setReconnectAtTxEnd(property); + } + } + + public void setRelaxAutoCommit(boolean property) { + super.setRelaxAutoCommit(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRelaxAutoCommit(property); + } + } + + public void setReportMetricsIntervalMillis(int millis) throws SQLException { + super.setReportMetricsIntervalMillis(millis); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setReportMetricsIntervalMillis(millis); + } + } + + public void setRequireSSL(boolean property) { + super.setRequireSSL(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRequireSSL(property); + } + } + + public void setRetainStatementAfterResultSetClose(boolean flag) { + super.setRetainStatementAfterResultSetClose(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRetainStatementAfterResultSetClose(flag); + } + } + + public void setRollbackOnPooledClose(boolean flag) { + super.setRollbackOnPooledClose(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRollbackOnPooledClose(flag); + } + } + + public void setRoundRobinLoadBalance(boolean flag) { + super.setRoundRobinLoadBalance(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRoundRobinLoadBalance(flag); + } + } + + public void setRunningCTS13(boolean flag) { + super.setRunningCTS13(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRunningCTS13(flag); + } + } + + public void setSecondsBeforeRetryMaster(int property) throws SQLException { + super.setSecondsBeforeRetryMaster(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSecondsBeforeRetryMaster(property); + } + } + + public void setServerTimezone(String property) { + super.setServerTimezone(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setServerTimezone(property); + } + } + + public void setSessionVariables(String variables) { + super.setSessionVariables(variables); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSessionVariables(variables); + } + } + + public void setSlowQueryThresholdMillis(int millis) throws SQLException { + super.setSlowQueryThresholdMillis(millis); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSlowQueryThresholdMillis(millis); + } + } + + public void setSocketFactoryClassName(String property) { + super.setSocketFactoryClassName(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSocketFactoryClassName(property); + } + } + + public void setSocketTimeout(int property) throws SQLException { + super.setSocketTimeout(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSocketTimeout(property); + } + } + + public void setStrictFloatingPoint(boolean property) { + super.setStrictFloatingPoint(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setStrictFloatingPoint(property); + } + } + + public void setStrictUpdates(boolean property) { + super.setStrictUpdates(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setStrictUpdates(property); + } + } + + public void setTinyInt1isBit(boolean flag) { + super.setTinyInt1isBit(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTinyInt1isBit(flag); + } + } + + public void setTraceProtocol(boolean flag) { + super.setTraceProtocol(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTraceProtocol(flag); + } + } + + public void setTransformedBitIsBoolean(boolean flag) { + super.setTransformedBitIsBoolean(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTransformedBitIsBoolean(flag); + } + } + + public void setUseCompression(boolean property) { + super.setUseCompression(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseCompression(property); + } + } + + public void setUseFastIntParsing(boolean flag) { + super.setUseFastIntParsing(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseFastIntParsing(flag); + } + } + + public void setUseHostsInPrivileges(boolean property) { + super.setUseHostsInPrivileges(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseHostsInPrivileges(property); + } + } + + public void setUseInformationSchema(boolean flag) { + super.setUseInformationSchema(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseInformationSchema(flag); + } + } + + public void setUseLocalSessionState(boolean flag) { + super.setUseLocalSessionState(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseLocalSessionState(flag); + } + } + + public void setUseOldUTF8Behavior(boolean flag) { + super.setUseOldUTF8Behavior(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseOldUTF8Behavior(flag); + } + } + + public void setUseOnlyServerErrorMessages(boolean flag) { + super.setUseOnlyServerErrorMessages(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseOnlyServerErrorMessages(flag); + } + } + + public void setUseReadAheadInput(boolean flag) { + super.setUseReadAheadInput(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseReadAheadInput(flag); + } + } + + public void setUseServerPreparedStmts(boolean flag) { + super.setUseServerPreparedStmts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseServerPreparedStmts(flag); + } + } + + public void setUseSqlStateCodes(boolean flag) { + super.setUseSqlStateCodes(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseSqlStateCodes(flag); + } + } + + public void setUseSSL(boolean property) { + super.setUseSSL(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseSSL(property); + } + } + + public void setUseStreamLengthsInPrepStmts(boolean property) { + super.setUseStreamLengthsInPrepStmts(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseStreamLengthsInPrepStmts(property); + } + } + + public void setUseTimezone(boolean property) { + super.setUseTimezone(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseTimezone(property); + } + } + + public void setUseUltraDevWorkAround(boolean property) { + super.setUseUltraDevWorkAround(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseUltraDevWorkAround(property); + } + } + + public void setUseUnbufferedInput(boolean flag) { + super.setUseUnbufferedInput(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseUnbufferedInput(flag); + } + } + + public void setUseUnicode(boolean flag) { + super.setUseUnicode(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseUnicode(flag); + } + } + + public void setUseUsageAdvisor(boolean useUsageAdvisorFlag) { + super.setUseUsageAdvisor(useUsageAdvisorFlag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseUsageAdvisor(useUsageAdvisorFlag); + } + } + + public void setYearIsDateType(boolean flag) { + super.setYearIsDateType(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setYearIsDateType(flag); + } + } + + public void setZeroDateTimeBehavior(String behavior) { + super.setZeroDateTimeBehavior(behavior); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setZeroDateTimeBehavior(behavior); + } + } + + public void setUseCursorFetch(boolean flag) { + super.setUseCursorFetch(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseCursorFetch(flag); + } + } + + public void setOverrideSupportsIntegrityEnhancementFacility(boolean flag) { + super.setOverrideSupportsIntegrityEnhancementFacility(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setOverrideSupportsIntegrityEnhancementFacility(flag); + } + } + + public void setNoTimezoneConversionForTimeType(boolean flag) { + super.setNoTimezoneConversionForTimeType(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setNoTimezoneConversionForTimeType(flag); + } + } + + public void setUseJDBCCompliantTimezoneShift(boolean flag) { + super.setUseJDBCCompliantTimezoneShift(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseJDBCCompliantTimezoneShift(flag); + } + } + + public void setAutoClosePStmtStreams(boolean flag) { + super.setAutoClosePStmtStreams(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoClosePStmtStreams(flag); + } + } + + public void setProcessEscapeCodesForPrepStmts(boolean flag) { + super.setProcessEscapeCodesForPrepStmts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setProcessEscapeCodesForPrepStmts(flag); + } + } + + public void setUseGmtMillisForDatetimes(boolean flag) { + super.setUseGmtMillisForDatetimes(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseGmtMillisForDatetimes(flag); + } + } + + public void setDumpMetadataOnColumnNotFound(boolean flag) { + super.setDumpMetadataOnColumnNotFound(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDumpMetadataOnColumnNotFound(flag); + } + } + + public void setResourceId(String resourceId) { + super.setResourceId(resourceId); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setResourceId(resourceId); + } + } + + public void setRewriteBatchedStatements(boolean flag) { + super.setRewriteBatchedStatements(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRewriteBatchedStatements(flag); + } + } + + public void setJdbcCompliantTruncationForReads(boolean jdbcCompliantTruncationForReads) { + super.setJdbcCompliantTruncationForReads(jdbcCompliantTruncationForReads); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setJdbcCompliantTruncationForReads(jdbcCompliantTruncationForReads); + } + } + + public void setUseJvmCharsetConverters(boolean flag) { + super.setUseJvmCharsetConverters(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseJvmCharsetConverters(flag); + } + } + + public void setPinGlobalTxToPhysicalConnection(boolean flag) { + super.setPinGlobalTxToPhysicalConnection(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPinGlobalTxToPhysicalConnection(flag); + } + } + + public void setGatherPerfMetrics(boolean flag) { + super.setGatherPerfMetrics(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setGatherPerfMetrics(flag); + } + } + + public void setUltraDevHack(boolean flag) { + super.setUltraDevHack(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUltraDevHack(flag); + } + } + + public void setInteractiveClient(boolean property) { + super.setInteractiveClient(property); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setInteractiveClient(property); + } + } + + public void setSocketFactory(String name) { + super.setSocketFactory(name); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSocketFactory(name); + } + } + + public void setUseServerPrepStmts(boolean flag) { + super.setUseServerPrepStmts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseServerPrepStmts(flag); + } + } + + public void setCacheCallableStmts(boolean flag) { + super.setCacheCallableStmts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCacheCallableStmts(flag); + } + } + + public void setCachePrepStmts(boolean flag) { + super.setCachePrepStmts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCachePrepStmts(flag); + } + } + + public void setCallableStmtCacheSize(int cacheSize) throws SQLException { + super.setCallableStmtCacheSize(cacheSize); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCallableStmtCacheSize(cacheSize); + } + } + + public void setPrepStmtCacheSize(int cacheSize) throws SQLException { + super.setPrepStmtCacheSize(cacheSize); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPrepStmtCacheSize(cacheSize); + } + } + + public void setPrepStmtCacheSqlLimit(int sqlLimit) throws SQLException { + super.setPrepStmtCacheSqlLimit(sqlLimit); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPrepStmtCacheSqlLimit(sqlLimit); + } + } + + public void setNoAccessToProcedureBodies(boolean flag) { + super.setNoAccessToProcedureBodies(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setNoAccessToProcedureBodies(flag); + } + } + + public void setUseOldAliasMetadataBehavior(boolean flag) { + super.setUseOldAliasMetadataBehavior(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseOldAliasMetadataBehavior(flag); + } + } + + public void setClientCertificateKeyStorePassword(String value) { + super.setClientCertificateKeyStorePassword(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setClientCertificateKeyStorePassword(value); + } + } + + public void setClientCertificateKeyStoreType(String value) { + super.setClientCertificateKeyStoreType(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setClientCertificateKeyStoreType(value); + } + } + + public void setClientCertificateKeyStoreUrl(String value) { + super.setClientCertificateKeyStoreUrl(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setClientCertificateKeyStoreUrl(value); + } + } + + public void setTrustCertificateKeyStorePassword(String value) { + super.setTrustCertificateKeyStorePassword(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTrustCertificateKeyStorePassword(value); + } + } + + public void setTrustCertificateKeyStoreType(String value) { + super.setTrustCertificateKeyStoreType(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTrustCertificateKeyStoreType(value); + } + } + + public void setTrustCertificateKeyStoreUrl(String value) { + super.setTrustCertificateKeyStoreUrl(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTrustCertificateKeyStoreUrl(value); + } + } + + public void setUseSSPSCompatibleTimezoneShift(boolean flag) { + super.setUseSSPSCompatibleTimezoneShift(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseSSPSCompatibleTimezoneShift(flag); + } + } + + public void setTreatUtilDateAsTimestamp(boolean flag) { + super.setTreatUtilDateAsTimestamp(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTreatUtilDateAsTimestamp(flag); + } + } + + public void setUseFastDateParsing(boolean flag) { + super.setUseFastDateParsing(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseFastDateParsing(flag); + } + } + + public void setLocalSocketAddress(String address) { + super.setLocalSocketAddress(address); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLocalSocketAddress(address); + } + } + + public void setUseConfigs(String configs) { + super.setUseConfigs(configs); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseConfigs(configs); + } + } + + public void setGenerateSimpleParameterMetadata(boolean flag) { + super.setGenerateSimpleParameterMetadata(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setGenerateSimpleParameterMetadata(flag); + } + } + + public void setLogXaCommands(boolean flag) { + super.setLogXaCommands(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLogXaCommands(flag); + } + } + + public void setResultSetSizeThreshold(int threshold) throws SQLException { + super.setResultSetSizeThreshold(threshold); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setResultSetSizeThreshold(threshold); + } + } + + public void setNetTimeoutForStreamingResults(int value) throws SQLException { + super.setNetTimeoutForStreamingResults(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setNetTimeoutForStreamingResults(value); + } + } + + public void setEnableQueryTimeouts(boolean flag) { + super.setEnableQueryTimeouts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setEnableQueryTimeouts(flag); + } + } + + public void setPadCharsWithSpace(boolean flag) { + super.setPadCharsWithSpace(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPadCharsWithSpace(flag); + } + } + + public void setUseDynamicCharsetInfo(boolean flag) { + super.setUseDynamicCharsetInfo(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseDynamicCharsetInfo(flag); + } + } + + public void setClientInfoProvider(String classname) { + super.setClientInfoProvider(classname); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setClientInfoProvider(classname); + } + } + + public void setPopulateInsertRowWithDefaultValues(boolean flag) { + super.setPopulateInsertRowWithDefaultValues(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPopulateInsertRowWithDefaultValues(flag); + } + } + + public void setLoadBalanceStrategy(String strategy) { + super.setLoadBalanceStrategy(strategy); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceStrategy(strategy); + } + } + + public void setTcpNoDelay(boolean flag) { + super.setTcpNoDelay(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTcpNoDelay(flag); + } + } + + public void setTcpKeepAlive(boolean flag) { + super.setTcpKeepAlive(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTcpKeepAlive(flag); + } + } + + public void setTcpRcvBuf(int bufSize) throws SQLException { + super.setTcpRcvBuf(bufSize); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTcpRcvBuf(bufSize); + } + } + + public void setTcpSndBuf(int bufSize) throws SQLException { + super.setTcpSndBuf(bufSize); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTcpSndBuf(bufSize); + } + } + + public void setTcpTrafficClass(int classFlags) throws SQLException { + super.setTcpTrafficClass(classFlags); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setTcpTrafficClass(classFlags); + } + } + + public void setUseNanosForElapsedTime(boolean flag) { + super.setUseNanosForElapsedTime(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseNanosForElapsedTime(flag); + } + } + + public void setSlowQueryThresholdNanos(long nanos) throws SQLException { + super.setSlowQueryThresholdNanos(nanos); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSlowQueryThresholdNanos(nanos); + } + } + + public void setStatementInterceptors(String value) { + super.setStatementInterceptors(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setStatementInterceptors(value); + } + } + + public void setUseDirectRowUnpack(boolean flag) { + super.setUseDirectRowUnpack(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseDirectRowUnpack(flag); + } + } + + public void setLargeRowSizeThreshold(String value) throws SQLException { + super.setLargeRowSizeThreshold(value); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLargeRowSizeThreshold(value); + } + } + + public void setUseBlobToStoreUTF8OutsideBMP(boolean flag) { + super.setUseBlobToStoreUTF8OutsideBMP(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseBlobToStoreUTF8OutsideBMP(flag); + } + } + + public void setUtf8OutsideBmpExcludedColumnNamePattern(String regexPattern) { + super.setUtf8OutsideBmpExcludedColumnNamePattern(regexPattern); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUtf8OutsideBmpExcludedColumnNamePattern(regexPattern); + } + } + + public void setUtf8OutsideBmpIncludedColumnNamePattern(String regexPattern) { + super.setUtf8OutsideBmpIncludedColumnNamePattern(regexPattern); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUtf8OutsideBmpIncludedColumnNamePattern(regexPattern); + } + } + + public void setIncludeInnodbStatusInDeadlockExceptions(boolean flag) { + super.setIncludeInnodbStatusInDeadlockExceptions(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setIncludeInnodbStatusInDeadlockExceptions(flag); + } + } + + public void setIncludeThreadDumpInDeadlockExceptions(boolean flag) { + super.setIncludeThreadDumpInDeadlockExceptions(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setIncludeThreadDumpInDeadlockExceptions(flag); + } + } + + public void setIncludeThreadNamesAsStatementComment(boolean flag) { + super.setIncludeThreadNamesAsStatementComment(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setIncludeThreadNamesAsStatementComment(flag); + } + } + + public void setBlobsAreStrings(boolean flag) { + super.setBlobsAreStrings(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setBlobsAreStrings(flag); + } + } + + public void setFunctionsNeverReturnBlobs(boolean flag) { + super.setFunctionsNeverReturnBlobs(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setFunctionsNeverReturnBlobs(flag); + } + } + + public void setAutoSlowLog(boolean flag) { + super.setAutoSlowLog(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAutoSlowLog(flag); + } + } + + public void setConnectionLifecycleInterceptors(String interceptors) { + super.setConnectionLifecycleInterceptors(interceptors); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setConnectionLifecycleInterceptors(interceptors); + } + } + + public void setProfilerEventHandler(String handler) { + super.setProfilerEventHandler(handler); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setProfilerEventHandler(handler); + } + } + + public void setVerifyServerCertificate(boolean flag) { + super.setVerifyServerCertificate(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setVerifyServerCertificate(flag); + } + } + + public void setUseLegacyDatetimeCode(boolean flag) { + super.setUseLegacyDatetimeCode(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseLegacyDatetimeCode(flag); + } + } + + public void setSelfDestructOnPingSecondsLifetime(int seconds) throws SQLException { + super.setSelfDestructOnPingSecondsLifetime(seconds); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSelfDestructOnPingSecondsLifetime(seconds); + } + } + + public void setSelfDestructOnPingMaxOperations(int maxOperations) throws SQLException { + super.setSelfDestructOnPingMaxOperations(maxOperations); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setSelfDestructOnPingMaxOperations(maxOperations); + } + } + + public void setUseColumnNamesInFindColumn(boolean flag) { + super.setUseColumnNamesInFindColumn(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseColumnNamesInFindColumn(flag); + } + } + + public void setUseLocalTransactionState(boolean flag) { + super.setUseLocalTransactionState(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseLocalTransactionState(flag); + } + } + + public void setCompensateOnDuplicateKeyUpdateCounts(boolean flag) { + super.setCompensateOnDuplicateKeyUpdateCounts(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setCompensateOnDuplicateKeyUpdateCounts(flag); + } + } + + public void setUseAffectedRows(boolean flag) { + super.setUseAffectedRows(flag); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setUseAffectedRows(flag); + } + } + + public void setPasswordCharacterEncoding(String characterSet) { + super.setPasswordCharacterEncoding(characterSet); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setPasswordCharacterEncoding(characterSet); + } + } + + public void setLoadBalanceBlacklistTimeout(int loadBalanceBlacklistTimeout) throws SQLException { + super.setLoadBalanceBlacklistTimeout(loadBalanceBlacklistTimeout); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceBlacklistTimeout(loadBalanceBlacklistTimeout); + } + } + + public void setRetriesAllDown(int retriesAllDown) throws SQLException { + super.setRetriesAllDown(retriesAllDown); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setRetriesAllDown(retriesAllDown); + } + } + + public void setExceptionInterceptors(String exceptionInterceptors) { + super.setExceptionInterceptors(exceptionInterceptors); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setExceptionInterceptors(exceptionInterceptors); + } + } + + public void setQueryTimeoutKillsConnection(boolean queryTimeoutKillsConnection) { + super.setQueryTimeoutKillsConnection(queryTimeoutKillsConnection); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setQueryTimeoutKillsConnection(queryTimeoutKillsConnection); + } + } + + public void setLoadBalancePingTimeout(int loadBalancePingTimeout) throws SQLException { + super.setLoadBalancePingTimeout(loadBalancePingTimeout); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalancePingTimeout(loadBalancePingTimeout); + } + } + + public void setLoadBalanceValidateConnectionOnSwapServer(boolean loadBalanceValidateConnectionOnSwapServer) { + super.setLoadBalanceValidateConnectionOnSwapServer(loadBalanceValidateConnectionOnSwapServer); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceValidateConnectionOnSwapServer(loadBalanceValidateConnectionOnSwapServer); + } + } + + public void setLoadBalanceConnectionGroup(String loadBalanceConnectionGroup) { + super.setLoadBalanceConnectionGroup(loadBalanceConnectionGroup); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceConnectionGroup(loadBalanceConnectionGroup); + } + } + + public void setLoadBalanceExceptionChecker(String loadBalanceExceptionChecker) { + super.setLoadBalanceExceptionChecker(loadBalanceExceptionChecker); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceExceptionChecker(loadBalanceExceptionChecker); + } + } + + public void setLoadBalanceSQLStateFailover(String loadBalanceSQLStateFailover) { + super.setLoadBalanceSQLStateFailover(loadBalanceSQLStateFailover); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceSQLStateFailover(loadBalanceSQLStateFailover); + } + } + + public void setLoadBalanceSQLExceptionSubclassFailover(String loadBalanceSQLExceptionSubclassFailover) { + super.setLoadBalanceSQLExceptionSubclassFailover(loadBalanceSQLExceptionSubclassFailover); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceSQLExceptionSubclassFailover(loadBalanceSQLExceptionSubclassFailover); + } + } + + public void setLoadBalanceEnableJMX(boolean loadBalanceEnableJMX) { + super.setLoadBalanceEnableJMX(loadBalanceEnableJMX); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceEnableJMX(loadBalanceEnableJMX); + } + } + + public void setLoadBalanceAutoCommitStatementThreshold(int loadBalanceAutoCommitStatementThreshold) throws SQLException { + super.setLoadBalanceAutoCommitStatementThreshold(loadBalanceAutoCommitStatementThreshold); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceAutoCommitStatementThreshold(loadBalanceAutoCommitStatementThreshold); + } + } + + public void setLoadBalanceAutoCommitStatementRegex(String loadBalanceAutoCommitStatementRegex) { + super.setLoadBalanceAutoCommitStatementRegex(loadBalanceAutoCommitStatementRegex); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setLoadBalanceAutoCommitStatementRegex(loadBalanceAutoCommitStatementRegex); + } + } + + public void setAuthenticationPlugins(String authenticationPlugins) { + super.setAuthenticationPlugins(authenticationPlugins); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setAuthenticationPlugins(authenticationPlugins); + } + } + + public void setDisabledAuthenticationPlugins(String disabledAuthenticationPlugins) { + super.setDisabledAuthenticationPlugins(disabledAuthenticationPlugins); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDisabledAuthenticationPlugins(disabledAuthenticationPlugins); + } + } + + public void setDefaultAuthenticationPlugin(String defaultAuthenticationPlugin) { + super.setDefaultAuthenticationPlugin(defaultAuthenticationPlugin); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDefaultAuthenticationPlugin(defaultAuthenticationPlugin); + } + } + + public void setParseInfoCacheFactory(String factoryClassname) { + super.setParseInfoCacheFactory(factoryClassname); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setParseInfoCacheFactory(factoryClassname); + } + } + + public void setServerConfigCacheFactory(String factoryClassname) { + super.setServerConfigCacheFactory(factoryClassname); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setServerConfigCacheFactory(factoryClassname); + } + } + + public void setDisconnectOnExpiredPasswords(boolean disconnectOnExpiredPasswords) { + super.setDisconnectOnExpiredPasswords(disconnectOnExpiredPasswords); + for (ConnectionProperties cp : serverConnections.values()) { + cp.setDisconnectOnExpiredPasswords(disconnectOnExpiredPasswords); + } + } + + public void setGetProceduresReturnsFunctions(boolean getProcedureReturnsFunctions) { + super.setGetProceduresReturnsFunctions(getProcedureReturnsFunctions); + } + + // com.mysql.jdbc.Connection + + public int getActiveStatementCount() { + return -1; + } + + public long getIdleFor() { + return -1; + } + + public Log getLog() throws SQLException { + return null; + } + + public String getServerCharacterEncoding() { + return null; + } + + public TimeZone getServerTimezoneTZ() { + return null; + } + + public boolean isMasterConnection() { + return false; + } + + public boolean isNoBackslashEscapesSet() { + return false; + } + + public boolean isSameResource(Connection c) { + return false; + } + + public boolean parserKnowsUnicode() { + return false; + } + + public void ping() throws SQLException { + } + + public void resetServerState() throws SQLException { + } + + public void setFailedOver(boolean flag) { + } + + public void setPreferSlaveDuringFailover(boolean flag) { + } + + public void setStatementComment(String comment) { + } + + public void reportQueryTime(long millisOrNanos) { + } + + public boolean isAbonormallyLongQuery(long millisOrNanos) { + return false; + } + + public void initializeExtension(Extension ex) throws SQLException { + } + + public int getAutoIncrementIncrement() { + return -1; + } + + public boolean hasSameProperties(Connection c) { + return false; + } + + public Properties getProperties() { + return null; + } + + public void setSchema(String schema) throws SQLException { + } + + public String getSchema() throws SQLException { + return null; + } + + public void abort(Executor executor) throws SQLException { + } + + public void setNetworkTimeout(Executor executor, final int milliseconds) throws SQLException { + } + + public int getNetworkTimeout() throws SQLException { + return -1; + } + + public void checkClosed() throws SQLException { + } + + public Object getConnectionMutex() { + return this; + } + + public void setSessionMaxRows(int max) throws SQLException { + for (Connection c : serverConnections.values()) { + c.setSessionMaxRows(max); + } + } + + public int getSessionMaxRows() { + return getActiveConnectionPassive().getSessionMaxRows(); + } + + // MySQLConnection + public boolean isProxySet() { + return false; + } + + public Connection duplicate() throws SQLException { + return null; + } + + public CachedResultSetMetaData getCachedMetaData(String sql) { + return null; + } + + public Calendar getCalendarInstanceForSessionOrNew() { + return null; + } + + public Timer getCancelTimer() { + return null; + } + + public String getCharacterSetMetadata() { + return null; + } + + public SingleByteCharsetConverter getCharsetConverter(String javaEncodingName) + throws SQLException { + return null; + } + + public String getCharsetNameForIndex(int charsetIndex) throws SQLException { + return null; + } + + public TimeZone getDefaultTimeZone() { + return null; + } + + public String getErrorMessageEncoding() { + return null; + } + + public ExceptionInterceptor getExceptionInterceptor() { + if (this.currentConnection == null) { + return null; + } + + return getActiveConnectionPassive().getExceptionInterceptor(); + } + + public String getHost() { + return null; + } + + public long getId() { + return -1; + } + + public int getMaxBytesPerChar(String javaCharsetName) throws SQLException { + return -1; + } + + public int getMaxBytesPerChar(Integer charsetIndex, String javaCharsetName) throws SQLException { + return -1; + } + + public java.sql.Statement getMetadataSafeStatement() throws SQLException { + return null; + } + + public int getNetBufferLength() { + return -1; + } + + public boolean getRequiresEscapingEncoder() { + return false; + } + + public int getServerMajorVersion() { + return -1; + } + + public int getServerMinorVersion() { + return -1; + } + + public int getServerSubMinorVersion() { + return -1; + } + + public String getServerVariable(String variableName) { + return null; + } + + public String getServerVersion() { + return null; + } + + public Calendar getSessionLockedCalendar() { + return null; + } + + public String getStatementComment() { + return null; + } + + public List getStatementInterceptorsInstances() { + return null; + } + + public String getURL() { + return null; + } + + public String getUser() { + return null; + } + + public Calendar getUtcCalendar() { + return null; + } + + public void incrementNumberOfPreparedExecutes() { + } + + public void incrementNumberOfPrepares() { + } + + public void incrementNumberOfResultSetsCreated() { + } + + public void initializeResultsMetadataFromCache(String sql, + CachedResultSetMetaData cachedMetaData, + ResultSetInternalMethods resultSet) throws SQLException { + } + + public void initializeSafeStatementInterceptors() throws SQLException { + } + + public boolean isClientTzUTC() { + return false; + } + + public boolean isCursorFetchEnabled() throws SQLException { + return false; + } + + public boolean isReadInfoMsgEnabled() { + return false; + } + + public boolean isServerTzUTC() { + return false; + } + + public boolean lowerCaseTableNames() { + return false; + } + + /** + * + * @param stmt + */ + public void maxRowsChanged(com.mysql.jdbc.Statement stmt) { + } + + public void pingInternal(boolean checkForClosedConnection, int timeoutMillis) + throws SQLException { + } + + public void realClose(boolean calledExplicitly, boolean issueRollback, + boolean skipLocalTeardown, Throwable reason) throws SQLException { + } + + public void recachePreparedStatement(ServerPreparedStatement pstmt) + throws SQLException { + } + + public void registerQueryExecutionTime(long queryTimeMs) { + } + + public void registerStatement(com.mysql.jdbc.Statement stmt) { + } + + public void reportNumberOfTablesAccessed(int numTablesAccessed) { + } + + public boolean serverSupportsConvertFn() throws SQLException { + return false; + } + + public void setReadInfoMsgEnabled(boolean flag) { + } + + public void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException { + } + + public boolean storesLowerCaseTableName() { + return false; + } + + public void throwConnectionClosedException() throws SQLException { + } + + public void unregisterStatement(com.mysql.jdbc.Statement stmt) { + } + + /** + * + * @param stmt + * @throws SQLException + */ + public void unsetMaxRows(com.mysql.jdbc.Statement stmt) throws SQLException { + } + + public boolean useAnsiQuotedIdentifiers() { + return false; + } + + public boolean useMaxRows() { + return false; + } + + // java.sql.Connection + public void clearWarnings() { + } + + public Properties getClientInfo() { + return null; + } + + /** + * + * @param name + * @return + */ + public String getClientInfo(String name) { + return null; + } + + public int getHoldability() { + return -1; + } + + public int getTransactionIsolation() { + return -1; + } + + public Map> getTypeMap() { + return null; + } + + public SQLWarning getWarnings() { + return null; + } + + public String nativeSQL(String sql) { + return null; + } + + public ProfilerEventHandler getProfilerEventHandlerInstance() { + return null; + } + + public void setProfilerEventHandlerInstance(ProfilerEventHandler h) { + } + + public void decachePreparedStatement(ServerPreparedStatement pstmt) + throws SQLException { + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLDataSource.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLDataSource.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLDataSource.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,189 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.sql.Driver; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.Properties; + +import com.mysql.jdbc.NonRegisteringDriver; +import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; + +/** + * DataSource used to create connections to a MySQL fabric. + */ +public class FabricMySQLDataSource extends MysqlDataSource + implements FabricMySQLConnectionProperties { + + private static final long serialVersionUID = 1L; + + /** Driver used to create connections. */ + private final static Driver driver; + + static { + try { + driver = new FabricMySQLDriver(); + } catch (Exception ex) { + throw new RuntimeException("Can create driver", ex); + } + } + + /** + * Creates a connection using the specified properties. + * copied directly from MysqlDataSource.getConnection(). + * No easy way to override the static `mysqlDriver' without + * globally affecting the driver. + * + * @param props + * the properties to connect with + * + * @return a connection to the database + * + * @throws SQLException + * if an error occurs + */ + @Override + protected java.sql.Connection getConnection(Properties props) + throws SQLException { + String jdbcUrlToUse = null; + + if (!this.explicitUrl) { + StringBuffer jdbcUrl = new StringBuffer("jdbc:mysql:fabric://"); + + if (this.hostName != null) { + jdbcUrl.append(this.hostName); + } + + jdbcUrl.append(":"); + jdbcUrl.append(this.port); + jdbcUrl.append("/"); + + if (this.databaseName != null) { + jdbcUrl.append(this.databaseName); + } + + jdbcUrlToUse = jdbcUrl.toString(); + } else { + jdbcUrlToUse = this.url; + } + + // + // URL should take precedence over properties + // + + Properties urlProps = ((FabricMySQLDriver)driver).parseFabricURL(jdbcUrlToUse, null); + urlProps.remove(NonRegisteringDriver.DBNAME_PROPERTY_KEY); + urlProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY); + urlProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY); + + Iterator keys = urlProps.keySet().iterator(); + + while (keys.hasNext()) { + String key = (String)keys.next(); + + props.setProperty(key, urlProps.getProperty(key)); + } + + if (this.fabricShardKey != null) + props.setProperty(FabricMySQLDriver.FABRIC_SHARD_KEY_PROPERTY_KEY, this.fabricShardKey); + if (this.fabricShardTable != null) + props.setProperty(FabricMySQLDriver.FABRIC_SHARD_TABLE_PROPERTY_KEY, this.fabricShardTable); + if (this.fabricServerGroup != null) + props.setProperty(FabricMySQLDriver.FABRIC_SERVER_GROUP_PROPERTY_KEY, this.fabricServerGroup); + props.setProperty(FabricMySQLDriver.FABRIC_PROTOCOL_PROPERTY_KEY, this.fabricProtocol); + if (this.fabricUsername != null) + props.setProperty(FabricMySQLDriver.FABRIC_USERNAME_PROPERTY_KEY, this.fabricUsername); + if (this.fabricPassword != null) + props.setProperty(FabricMySQLDriver.FABRIC_PASSWORD_PROPERTY_KEY, this.fabricPassword); + props.setProperty(FabricMySQLDriver.FABRIC_REPORT_ERRORS_PROPERTY_KEY, + Boolean.toString(this.fabricReportErrors)); + + return driver.connect(jdbcUrlToUse, props); + } + + private String fabricShardKey; + private String fabricShardTable; + private String fabricServerGroup; + private String fabricProtocol = "http"; + private String fabricUsername; + private String fabricPassword; + private boolean fabricReportErrors = false; + + public void setFabricShardKey(String value) { + this.fabricShardKey = value; + } + + public String getFabricShardKey() { + return this.fabricShardKey; + } + + public void setFabricShardTable(String value) { + this.fabricShardTable = value; + } + + public String getFabricShardTable() { + return this.fabricShardTable; + } + + public void setFabricServerGroup(String value) { + this.fabricServerGroup = value; + } + + public String getFabricServerGroup() { + return this.fabricServerGroup; + } + + public void setFabricProtocol(String value) { + this.fabricProtocol = value; + } + + public String getFabricProtocol() { + return this.fabricProtocol; + } + + public void setFabricUsername(String value) { + this.fabricUsername = value; + } + + public String getFabricUsername() { + return this.fabricUsername; + } + + public void setFabricPassword(String value) { + this.fabricPassword = value; + } + + public String getFabricPassword() { + return this.fabricPassword; + } + + public void setFabricReportErrors(boolean value) { + this.fabricReportErrors = value; + } + + public boolean getFabricReportErrors() { + return this.fabricReportErrors; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLDriver.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLDriver.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/FabricMySQLDriver.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,107 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.lang.reflect.Constructor; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import java.util.logging.Logger; +import com.mysql.jdbc.NonRegisteringDriver; + +/** + * JDBC driver for Fabric MySQL connections. This driver will create connections for URLs of the form: + * jdbc:mysql:fabric://host:port/?fabricShardTable=employees.employees&fabricShardKey=4621. + */ +public class FabricMySQLDriver extends NonRegisteringDriver implements Driver { + // may be extended to support other protocols in the future + public static final String FABRIC_URL_PREFIX = "jdbc:mysql:fabric://"; + + // connection property keys + public static final String FABRIC_SHARD_KEY_PROPERTY_KEY = "fabricShardKey"; + public static final String FABRIC_SHARD_TABLE_PROPERTY_KEY = "fabricShardTable"; + public static final String FABRIC_SERVER_GROUP_PROPERTY_KEY = "fabricServerGroup"; + public static final String FABRIC_PROTOCOL_PROPERTY_KEY = "fabricProtocol"; + public static final String FABRIC_USERNAME_PROPERTY_KEY = "fabricUsername"; + public static final String FABRIC_PASSWORD_PROPERTY_KEY = "fabricPassword"; + public static final String FABRIC_REPORT_ERRORS_PROPERTY_KEY = "fabricReportErrors"; + + // Register ourselves with the DriverManager + static { + try { + DriverManager.registerDriver(new FabricMySQLDriver()); + } catch (SQLException ex) { + throw new RuntimeException("Can't register driver", ex); + } + } + + public FabricMySQLDriver() throws SQLException { + } + + public Connection connect(String url, Properties info) throws SQLException { + Properties parsedProps = parseFabricURL(url, info); + + if (parsedProps == null) { + return null; + } + + parsedProps.setProperty(FABRIC_PROTOCOL_PROPERTY_KEY, "http"); + if (com.mysql.jdbc.Util.isJdbc4()) { + try { + Constructor jdbc4proxy = Class.forName( + "com.mysql.fabric.jdbc.JDBC4FabricMySQLConnectionProxy").getConstructor( + new Class[] { Properties.class }); + return (Connection) com.mysql.jdbc.Util.handleNewInstance(jdbc4proxy, + new Object[] { parsedProps }, null); + } catch (Exception e) { + throw (SQLException) new SQLException(e.getMessage()).initCause(e); + } + } + + return new FabricMySQLConnectionProxy(parsedProps); + } + + /** + * Determine whether this is a valid Fabric MySQL URL. It should be of the form: + * jdbc:mysql:fabric://host:port/?options. + */ + public boolean acceptsURL(String url) throws SQLException { + return parseFabricURL(url, null) != null; + } + + /* static */ Properties parseFabricURL(String url, Properties defaults) throws SQLException { + if (!url.startsWith("jdbc:mysql:fabric://")) + return null; + // We have to fudge the URL here to get NonRegisteringDriver.parseURL() to parse it for us. + // It actually checks the prefix and bails if it's not recognized. + // jdbc:mysql:fabric:// => jdbc:mysql:// + return super.parseURL(url.replaceAll("fabric:", ""), defaults); + } + + public Logger getParentLogger() throws SQLException { + throw new SQLException("no logging"); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/JDBC4FabricMySQLConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/JDBC4FabricMySQLConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/JDBC4FabricMySQLConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,103 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.sql.SQLException; +import java.util.Set; + +import com.mysql.fabric.Server; +import com.mysql.fabric.ServerGroup; + +/** + * + */ +public interface JDBC4FabricMySQLConnection extends com.mysql.jdbc.JDBC4MySQLConnection { + /** + * Clear all the state that is used to determine which server to + * send queries to. + */ + void clearServerSelectionCriteria() throws SQLException; + + /** + * Set the shard key for the data being accessed. + */ + void setShardKey(String shardKey) throws SQLException; + + /** + * Get the shard key for the data being accessed. + */ + String getShardKey(); + + /** + * Set the table being accessed. Can be a table name or a + * "database.table" pair. The table must be known by Fabric + * as a sharded table. + */ + void setShardTable(String shardTable) throws SQLException; + + /** + * Get the table being accessed. + */ + String getShardTable(); + + /** + * Set the server group name to connect to. Direct server group selection + * is mutually exclusive of sharded data access. + */ + void setServerGroupName(String serverGroupName) throws SQLException; + + /** + * Get the server group name when using direct server group selection. + */ + String getServerGroupName(); + + /** + * Get the current server group. + * @returns The currently chosen group if sufficient server group selection + * criteria has been provided. Otherwise null. + */ + ServerGroup getCurrentServerGroup(); + + /** + * Clear the list of tables for the last query. This also clears the + * shard mapping/table and must be given again for the next query via + * {@link setShardTable} or {@addQueryTable}. + */ + void clearQueryTables() throws SQLException; + + /** + * Add a table to the set of tables used for the next query on this connection. + * This is used for: + *
    + *
  • Choosing a shard given the tables used
  • + *
  • Preventing cross-shard queries
  • + *
+ */ + void addQueryTable(String tableName) throws SQLException; + + /** + * The set of tables to be used in the next query on this connection. + */ + Set getQueryTables(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/JDBC4FabricMySQLConnectionProxy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/JDBC4FabricMySQLConnectionProxy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/jdbc/JDBC4FabricMySQLConnectionProxy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,146 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.jdbc; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Savepoint; +import java.sql.Struct; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TimerTask; +import java.util.Timer; +import java.util.TimeZone; +import java.util.concurrent.Executor; + +import com.mysql.jdbc.Buffer; +import com.mysql.jdbc.CachedResultSetMetaData; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ConnectionProperties; +import com.mysql.jdbc.ConnectionPropertiesImpl; +import com.mysql.jdbc.ExceptionInterceptor; +import com.mysql.jdbc.Extension; +import com.mysql.jdbc.Field; +import com.mysql.jdbc.JDBC4Connection; +import com.mysql.jdbc.JDBC4MySQLConnection; +import com.mysql.jdbc.MySQLConnection; +import com.mysql.jdbc.MysqlIO; +import com.mysql.jdbc.NonRegisteringDriver; +import com.mysql.jdbc.ResultSetInternalMethods; +import com.mysql.jdbc.ServerPreparedStatement; +import com.mysql.jdbc.SingleByteCharsetConverter; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.StatementImpl; +import com.mysql.jdbc.StatementInterceptorV2; +import com.mysql.jdbc.log.Log; + +import com.mysql.fabric.FabricCommunicationException; +import com.mysql.fabric.FabricConnection; +import com.mysql.fabric.Server; +import com.mysql.fabric.ServerGroup; +import com.mysql.fabric.ServerMode; +import com.mysql.fabric.ShardMapping; + +/** + * + * Limitations: + *
    + *
  • One shard table can be specified
  • + *
  • One shard key can be specified
  • + *
+ */ +public class JDBC4FabricMySQLConnectionProxy extends FabricMySQLConnectionProxy + implements JDBC4FabricMySQLConnection, FabricMySQLConnectionProperties { + + private FabricConnection fabricConnection; + + public JDBC4FabricMySQLConnectionProxy(Properties props) throws SQLException { + super(props); + } + + public Blob createBlob() { + try { + transactionBegun(); + return getActiveConnection().createBlob(); + } catch(SQLException ex) { + throw new RuntimeException(ex); + } + } + + public Clob createClob() { + try { + transactionBegun(); + return getActiveConnection().createClob(); + } catch(SQLException ex) { + throw new RuntimeException(ex); + } + } + + public NClob createNClob() { + try { + transactionBegun(); + return getActiveConnection().createNClob(); + } catch(SQLException ex) { + throw new RuntimeException(ex); + } + } + + public SQLXML createSQLXML() throws SQLException { + transactionBegun(); + return getActiveConnection().createSQLXML(); + } + + public void setClientInfo(Properties properties) throws SQLClientInfoException { + for (Connection c : serverConnections.values()) + c.setClientInfo(properties); + } + + public void setClientInfo(String name, String value) throws SQLClientInfoException { + for (Connection c : serverConnections.values()) + c.setClientInfo(name, value); + } + + public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return getActiveConnection().createArrayOf(typeName, elements); + } + + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + transactionBegun(); + return getActiveConnection().createStruct(typeName, attributes); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/AuthenticatedXmlRpcMethodCaller.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/AuthenticatedXmlRpcMethodCaller.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/AuthenticatedXmlRpcMethodCaller.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,77 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.proto.xmlrpc; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import com.mysql.fabric.FabricCommunicationException; + +/** + * An XML-RPC method caller which wraps another caller with RFC-2617 + * authentication. + */ +public class AuthenticatedXmlRpcMethodCaller implements XmlRpcMethodCaller { + private XmlRpcMethodCaller underlyingCaller; + + private String url; + private String username; + private String password; + + public AuthenticatedXmlRpcMethodCaller(XmlRpcMethodCaller underlyingCaller, String url, String username, String password) { + this.underlyingCaller = underlyingCaller; + this.url = url; + this.username = username; + this.password = password; + } + + public void setHeader(String name, String value) { + underlyingCaller.setHeader(name, value); + } + + public void clearHeader(String name) { + underlyingCaller.clearHeader(name); + } + + public List call(String methodName, Object args[]) + throws FabricCommunicationException { + String authenticateHeader; + + try { + authenticateHeader = DigestAuthentication.getChallengeHeader(this.url); + } catch (IOException ex) { + throw new FabricCommunicationException("Unable to obtain challenge header for authentication", ex); + } + + Map digestChallenge = DigestAuthentication.parseDigestChallenge(authenticateHeader); + + String authorizationHeader = DigestAuthentication + .generateAuthorizationHeader(digestChallenge, this.username, this.password); + + this.underlyingCaller.setHeader("Authorization", authorizationHeader); + + return this.underlyingCaller.call(methodName, args); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/DigestAuthentication.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/DigestAuthentication.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/DigestAuthentication.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,226 @@ +/* + Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.proto.xmlrpc; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * HTTP/1.1 Digest Authentication - RFC 2617 + */ +public class DigestAuthentication { + + /** + * Get the digest challenge header by connecting to the resource + * with no credentials. + */ + public static String getChallengeHeader(String url) throws IOException { + HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection(); + conn.setDoOutput(true); + conn.getOutputStream().close(); + try { + conn.getInputStream().close(); + } catch (IOException ex) { + // we expect a 401-unauthorized response with the + // WWW-Authenticate header to create the request with the + // necessary auth data + if (401 != conn.getResponseCode()) { + throw ex; + } + String hdr = conn.getHeaderField("WWW-Authenticate"); + if (hdr != null && !"".equals(hdr)) { + return hdr; + } + } + return null; + } + + /** + * Calculate the request digest for algorithm=MD5. + */ + public static String calculateMD5RequestDigest(String uri, String username, String password, String realm, + String nonce, String nc, String cnonce, String qop) { + String reqA1 = username + ":" + realm + ":" + password; + // valid only for qop="auth" + String reqA2 = "POST:" + uri; + + String hashA1 = checksumMD5(reqA1); + String hashA2 = checksumMD5(reqA2); + String requestDigest = digestMD5(hashA1, + nonce + ":" + + nc + ":" + + cnonce + ":" + + qop + ":" + + hashA2); + + return requestDigest; + } + + /** + * MD5 version of the "H()" function from rfc2617. + */ + private static String checksumMD5(String data) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch(NoSuchAlgorithmException ex) { + throw new RuntimeException("Unable to create MD5 instance", ex); + } + // TODO encoding + return hexEncode(md5.digest(data.getBytes())); + } + + /** + * MD5 version of the "KD()" function from rfc2617. + */ + private static String digestMD5(String secret, String data) { + return checksumMD5(secret + ":" + data); + } + + /** + * hex-encode a byte array + */ + private static String hexEncode(byte data[]) { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < data.length; ++i) { + sb.append(String.format("%02x", data[i])); + } + return sb.toString(); + } + + /** + * Serialize a parameter map into a digest response. This is used + * as the "Authorization" header in the request. All parameters in + * the supplied map will be added to the header. + */ + public static String serializeDigestResponse(Map paramMap) { + StringBuffer sb = new StringBuffer("Digest "); + + boolean prefixComma = false; + for (Map.Entry entry : paramMap.entrySet()) { + if (!prefixComma) { + prefixComma = true; + } else { + sb.append(", "); + } + sb.append(entry.getKey()); + sb.append("="); + sb.append(entry.getValue()); + } + + return sb.toString(); + } + + /** + * Parse a digest challenge from the WWW-Authenticate header + * return as the initial response during the authentication + * exchange. + */ + public static Map parseDigestChallenge(String headerValue) { + if (!headerValue.startsWith("Digest ")) + throw new IllegalArgumentException("Header is not a digest challenge"); + + String params = headerValue.substring(7); + Map paramMap = new HashMap(); + for (String param : params.split(",\\s*")) { + String pieces[] = param.split("="); + paramMap.put(pieces[0], pieces[1].replaceAll("^\"(.*)\"$", "$1")); + } + return paramMap; + } + + /** + * Generate the cnonce value. This allows the client provide a + * value used in the digest calculation. Same as Python. (no + * motivation given for this algorithm) + */ + public static String generateCnonce(String nonce, String nc) { + // Random string, keep it in basic printable ASCII range + byte buf[] = new byte[8]; + new Random().nextBytes(buf); + for (int i = 0; i < 8; ++i) + buf[i] = (byte) (0x20 + (buf[i] % 95)); + + String combo = String.format("%s:%s:%s:%s", nonce, nc, + new Date().toGMTString(), + new String(buf)); + MessageDigest sha1 = null; + try { + sha1 = MessageDigest.getInstance("SHA-1"); + } catch(NoSuchAlgorithmException ex) { + throw new RuntimeException("Unable to create SHA-1 instance", ex); + } + + return hexEncode(sha1.digest(combo.getBytes())); + } + + /** + * Quote a parameter to be included in the header. Parameters with + * embedded quotes will be rejected. + */ + private static String quoteParam(String param) { + if (param.contains("\"") || param.contains("'")) { + throw new IllegalArgumentException("Invalid character in parameter"); + } + return "\"" + param + "\""; + } + + /** + * Generate the Authorization header to make the authenticated + * request. + */ + public static String generateAuthorizationHeader(Map digestChallenge, + String username, String password) { + String nonce = digestChallenge.get("nonce"); + String nc = "00000001"; + String cnonce = generateCnonce(nonce, nc); + String qop = "auth"; + String uri = "/RPC2"; + String realm = digestChallenge.get("realm"); + String opaque = digestChallenge.get("opaque"); + + String requestDigest = calculateMD5RequestDigest(uri, username, password, + realm, nonce, nc, cnonce, qop); + Map digestResponseMap = new HashMap(); + digestResponseMap.put("algorithm", "MD5"); + digestResponseMap.put("username", quoteParam(username)); + digestResponseMap.put("realm", quoteParam(realm)); + digestResponseMap.put("nonce", quoteParam(nonce)); + digestResponseMap.put("uri", quoteParam(uri)); + digestResponseMap.put("qop", qop); + digestResponseMap.put("nc", nc); + digestResponseMap.put("cnonce", quoteParam(cnonce)); + digestResponseMap.put("response", quoteParam(requestDigest)); + digestResponseMap.put("opaque", quoteParam(opaque)); + + return serializeDigestResponse(digestResponseMap); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/InternalXmlRpcMethodCaller.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/InternalXmlRpcMethodCaller.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/InternalXmlRpcMethodCaller.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,118 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.proto.xmlrpc; + +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.mysql.fabric.FabricCommunicationException; +import com.mysql.fabric.xmlrpc.Client; +import com.mysql.fabric.xmlrpc.base.Array; +import com.mysql.fabric.xmlrpc.base.Member; +import com.mysql.fabric.xmlrpc.base.MethodCall; +import com.mysql.fabric.xmlrpc.base.MethodResponse; +import com.mysql.fabric.xmlrpc.base.Param; +import com.mysql.fabric.xmlrpc.base.Params; +import com.mysql.fabric.xmlrpc.base.Struct; +import com.mysql.fabric.xmlrpc.base.Value; + +/** + * An XML-RPC method caller which uses the internal XML-RPC client + * library. + */ +public class InternalXmlRpcMethodCaller implements XmlRpcMethodCaller { + private Client xmlRpcClient; + + public InternalXmlRpcMethodCaller(String url) throws FabricCommunicationException { + try { + xmlRpcClient = new Client(url); + } catch(MalformedURLException ex) { + throw new FabricCommunicationException(ex); + } + } + + /** + * Unwrap the underlying object from the Value wrapper. + */ + private Object unwrapValue(Value v) { + if (v.getType() == Value.TYPE_array) { + return methodResponseArrayToList((Array)v.getValue()); + } else if (v.getType() == Value.TYPE_struct) { + Map s = new HashMap(); + for (Member m : ((Struct)v.getValue()).getMember()) { + s.put(m.getName(), unwrapValue(m.getValue())); + } + return s; + } + return v.getValue(); + } + + private List methodResponseArrayToList(Array array) { + List result = new ArrayList(); + for (Value v : array.getData().getValue()) { + result.add(unwrapValue(v)); + } + return result; + } + + public void setHeader(String name, String value) { + this.xmlRpcClient.setHeader(name, value); + } + + public void clearHeader(String name) { + this.xmlRpcClient.clearHeader(name); + } + + public List call(String methodName, Object args[]) throws FabricCommunicationException { + MethodCall methodCall = new MethodCall(); + Params p = new Params(); + if (args == null) { + args = new Object[] {}; + } + for (int i = 0; i < args.length; ++i) { + if (args[i] == null) { + throw new NullPointerException("nil args unsupported"); + } else if (String.class.isAssignableFrom(args[i].getClass())) { + p.addParam(new Param(new Value((String)args[i]))); + } else if (Double.class.isAssignableFrom(args[i].getClass())) { + p.addParam(new Param(new Value((Double)args[i]))); + } else if (Integer.class.isAssignableFrom(args[i].getClass())) { + p.addParam(new Param(new Value((Integer)args[i]))); + } else { + throw new IllegalArgumentException("Unknown argument type: " + args[i].getClass()); + } + } + methodCall.setMethodName(methodName); + methodCall.setParams(p); + try { + MethodResponse resp = this.xmlRpcClient.execute(methodCall); + return methodResponseArrayToList((Array)resp.getParams().getParam().get(0).getValue().getValue()); + } catch(Exception ex) { + throw new FabricCommunicationException("Error during call to `" + methodName + "' (args=" + args + ")", ex); //irrecoverable + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/XmlRpcClient.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/XmlRpcClient.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/XmlRpcClient.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,316 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.proto.xmlrpc; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.mysql.fabric.FabricCommunicationException; +import com.mysql.fabric.Server; +import com.mysql.fabric.ServerGroup; +import com.mysql.fabric.ServerMode; +import com.mysql.fabric.ServerRole; +import com.mysql.fabric.ShardIndex; +import com.mysql.fabric.ShardMapping; +import com.mysql.fabric.ShardMappingFactory; +import com.mysql.fabric.ShardTable; +import com.mysql.fabric.ShardingType; + +import com.mysql.fabric.DumpResponse; +import com.mysql.fabric.FabricStateResponse; +import com.mysql.fabric.Response; + +/** + * Fabric client using the XML-RPC protocol. + */ +public class XmlRpcClient { + private XmlRpcMethodCaller methodCaller; + + public XmlRpcClient(String url, String username, String password) throws FabricCommunicationException { + this.methodCaller = new InternalXmlRpcMethodCaller(url); + if (username != null && !"".equals(username) && password != null) { + this.methodCaller = new AuthenticatedXmlRpcMethodCaller(this.methodCaller, + url, username, password); + } + } + + /** + * Unmarshall a response representing a server. + * + * `sharding.lookup_servers' returns ['38dc041b-de86-11e2-a891-e281dccd6dba', '127.0.0.1:3402', True] + * `dump.servers' returns ['38dc041b-de86-11e2-a891-e281dccd6dba', 'shard1', '127.0.0.1', '3402', 3, 3, 1.0] + */ + private static Server unmarshallServer(List serverData) { + Server s = null; + if (serverData.size() <= 4) { + // first format + String hostnameAndPort[] = ((String)serverData.get(1)).split(":"); + String hostname = hostnameAndPort[0]; + int port = Integer.valueOf(hostnameAndPort[1]); + ServerRole role = (Boolean)serverData.get(2) ? ServerRole.PRIMARY : ServerRole.SECONDARY; + // get(3) = "Running" (optional...) shows up on getGroup(), but not getServersForKey() + s = new Server(null/* group name not known */, (String)serverData.get(0), hostname, + port, ServerMode.READ_WRITE, role, 1.0); + } else if (serverData.size() == 7) { + // second format + String uuid = (String)serverData.get(0); + String groupName = (String)serverData.get(1); + String hostname = (String)serverData.get(2); + int port = Integer.valueOf((String)serverData.get(3)); + ServerMode mode = ServerMode.getFromConstant((Integer)serverData.get(4)); + ServerRole role = ServerRole.getFromConstant((Integer)serverData.get(5)); + double weight = (Double)serverData.get(6); + s = new Server(groupName, uuid, hostname, port, mode, role, weight); + } + return s; + } + + /** + * Convert a list of string/string/bool to Server objects. + */ + private static Set toServerSet(List l) throws FabricCommunicationException { + Set servers = new HashSet(); + for (List serverData : l) { + Server s = unmarshallServer(serverData); + if (s == null) { + throw new FabricCommunicationException("Unknown format of server object"); + } + servers.add(s); + } + return servers; + } + + /** + * Call a method and return the result only if the call is successful. + * + * @throws FabricCommunicationException If comm fails or the server reports that the method call failed. + */ + private Object errorSafeCallMethod(String methodName, Object args[]) throws FabricCommunicationException { + List responseData = this.methodCaller.call(methodName, args); + Response response = new Response(responseData); + if (!response.isSuccessful()) { + throw new FabricCommunicationException("Call failed to method `" + methodName + "':\n" + response.getTraceString()); + } + return response.getReturnValue(); + } + + /** + * Call a dump.* method. + */ + private DumpResponse callDumpMethod(String methodName, Object args[]) + throws FabricCommunicationException { + List responseData = this.methodCaller.call(methodName, args); + return new DumpResponse(responseData); + } + + /** + * Return a list of Fabric servers. + */ + public List getFabricNames() throws FabricCommunicationException { + return callDumpMethod("dump.fabric_nodes", new Object[] {}).getReturnValue(); + } + + /** + * Return a list of groups present in this fabric. + */ + public Set getGroupNames() throws FabricCommunicationException { + Set groupNames = new HashSet(); + for (HashMap wrapped : (List>)errorSafeCallMethod("group.lookup_groups", null)) { + groupNames.add(wrapped.get("group_id")); + } + return groupNames; + } + + public ServerGroup getServerGroup(String groupName) throws FabricCommunicationException { + Set groups = getServerGroups(groupName).getData(); + if (groups.size() == 1) { + return groups.iterator().next(); + } + return null; + } + + public Set getServersForKey(String tableName, int key) throws FabricCommunicationException { + return toServerSet((List)errorSafeCallMethod("sharding.lookup_servers", new Object[] {tableName, key})); + } + + /** + * Facade for "dump.servers". + */ + public FabricStateResponse> getServerGroups(String groupPattern) throws FabricCommunicationException { + int version = 0; // necessary but unused + DumpResponse response = callDumpMethod("dump.servers", new Object[] {version, groupPattern}); + // collect all servers by group name + Map> serversByGroupName = new HashMap>(); + for (List server : (List) response.getReturnValue()) { + Server s = unmarshallServer(server); + if (serversByGroupName.get(s.getGroupName()) == null) { + serversByGroupName.put(s.getGroupName(), new HashSet()); + } + serversByGroupName.get(s.getGroupName()).add(s); + } + // create group set + Set serverGroups = new HashSet(); + for (Map.Entry> entry : serversByGroupName.entrySet()) { + ServerGroup g = new ServerGroup(entry.getKey(), entry.getValue()); + serverGroups.add(g); + } + return new FabricStateResponse>(serverGroups, response.getTtl()); + } + + public FabricStateResponse> getServerGroups() throws FabricCommunicationException { + return getServerGroups(""); + } + + private FabricStateResponse> getShardTables(String shardMappingId) throws FabricCommunicationException { + int version = 0; + Object args[] = new Object[] {version, shardMappingId}; + DumpResponse tablesResponse = callDumpMethod("dump.shard_tables", args); + Set tables = new HashSet(); + // construct the tables + for (List rawTable : (List) tablesResponse.getReturnValue()) { + String database = (String)rawTable.get(0); + String table = (String)rawTable.get(1); + String column = (String)rawTable.get(2); + String mappingId = (String)rawTable.get(3); + ShardTable st = new ShardTable(database, table, column); + tables.add(st); + } + return new FabricStateResponse>(tables, tablesResponse.getTtl()); + } + + private FabricStateResponse> getShardIndices(String shardMappingId) throws FabricCommunicationException { + int version = 0; + Object args[] = new Object[] {version, shardMappingId}; + DumpResponse indexResponse = callDumpMethod("dump.shard_index", args); + Set indices = new HashSet(); + + // construct the index + for (List rawIndexEntry : (List) indexResponse.getReturnValue()) { + String bound = (String)rawIndexEntry.get(0); + String mappingId = (String)rawIndexEntry.get(1); + String shardId = (String)rawIndexEntry.get(2); + String groupName = (String)rawIndexEntry.get(3); + ShardIndex si = new ShardIndex(bound, Integer.valueOf(shardId), groupName); + indices.add(si); + } + return new FabricStateResponse>(indices, indexResponse.getTtl()); + } + + /** + * Retrieve a set of complete shard mappings. The returned mappings include all information + * available about the mapping. + * @param shardMappingIdPattern the shard mapping id to retrieve + */ + public FabricStateResponse> getShardMappings(String shardMappingIdPattern) throws FabricCommunicationException { + int version = 0; + Object args[] = new Object[] {version, shardMappingIdPattern}; // common to all calls + DumpResponse mapsResponse = callDumpMethod("dump.shard_maps", args); + // use the lowest ttl of all the calls + long minExpireTimeMillis = System.currentTimeMillis() + (1000 * mapsResponse.getTtl()); + + // construct the maps + Set mappings = new HashSet(); + for (List rawMapping : (List) mapsResponse.getReturnValue()) { + String mappingId = (String)rawMapping.get(0); + ShardingType shardingType = ShardingType.valueOf((String)rawMapping.get(1)); + String globalGroupName = (String)rawMapping.get(2); + + FabricStateResponse> tables = getShardTables(mappingId); + FabricStateResponse> indices = getShardIndices(mappingId); + + if (tables.getExpireTimeMillis() < minExpireTimeMillis) + minExpireTimeMillis = tables.getExpireTimeMillis(); + if (indices.getExpireTimeMillis() < minExpireTimeMillis) + minExpireTimeMillis = indices.getExpireTimeMillis(); + + ShardMapping m = new ShardMappingFactory().createShardMapping(mappingId, shardingType, globalGroupName, + tables.getData(), indices.getData()); + mappings.add(m); + } + + return new FabricStateResponse>(mappings, minExpireTimeMillis); + } + + public FabricStateResponse> getShardMappings() throws FabricCommunicationException { + return getShardMappings(""); + } + + /** + * Create a new HA group. + */ + public void createGroup(String groupName) throws FabricCommunicationException { + errorSafeCallMethod("group.create", new Object[] {groupName}); + } + + /** + * Create a new server in the given group. + */ + public void createServerInGroup(String groupName, String hostname, int port) + throws FabricCommunicationException { + errorSafeCallMethod("group.add", new Object[] {groupName, hostname + ":" + port}); + } + + /** + * Create a new shard mapping. + * + * @param type method by which data is distributed to shards + * @param globalGroupName name of global group of the shard mapping + * @returns id of the new shard mapping. + */ + public int createShardMapping(ShardingType type, String globalGroupName) throws FabricCommunicationException { + return (Integer)errorSafeCallMethod("sharding.create_definition", new Object[] {type.toString(), globalGroupName}); + } + + public void createShardTable(int shardMappingId, String database, String table, String column) throws FabricCommunicationException { + errorSafeCallMethod("sharding.add_table", new Object[] {shardMappingId, database + "." + table, column}); + } + + public void createShardIndex(int shardMappingId, String groupNameLowerBoundList) throws FabricCommunicationException { + String status = "ENABLED"; + errorSafeCallMethod("sharding.add_shard", new Object[] {shardMappingId, groupNameLowerBoundList, status}); + } + + public void promoteServerInGroup(String groupName, String hostname, int port) throws FabricCommunicationException { + ServerGroup serverGroup = getServerGroup(groupName); + for (Server s : serverGroup.getServers()) { + if (s.getHostname().equals(hostname) && + s.getPort() == port) { + errorSafeCallMethod("group.promote", new Object[] {groupName, s.getUuid()}); + break; + } + } + } + + public void reportServerError(Server server, String errorDescription, boolean forceFaulty) throws FabricCommunicationException { + String reporter = "MySQL Connector/J"; + String command = "threat.report_error"; + if (forceFaulty) { + command = "threat.report_failure"; + } + errorSafeCallMethod(command, new Object[] {server.getUuid(), reporter, errorDescription}); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/XmlRpcMethodCaller.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/XmlRpcMethodCaller.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/proto/xmlrpc/XmlRpcMethodCaller.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,38 @@ +/* + Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.proto.xmlrpc; + +import java.util.List; + +import com.mysql.fabric.FabricCommunicationException; + +/** + * Implementations of this class perform XML-RPC method calls. + */ +public interface XmlRpcMethodCaller { + List call(String methodName, Object args[]) + throws FabricCommunicationException; + void setHeader(String name, String value); + void clearHeader(String name); +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/Client.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/Client.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/Client.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,115 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXException; + +import com.mysql.fabric.xmlrpc.base.MethodCall; +import com.mysql.fabric.xmlrpc.base.MethodResponse; +import com.mysql.fabric.xmlrpc.base.ResponseParser; +import com.mysql.fabric.xmlrpc.exceptions.MySQLFabricException; + +/** + * XML-RPC client. + */ +public class Client { + private URL url; + private Map headers = new HashMap(); + + public Client(String url) throws MalformedURLException { + this.url = new URL(url); + } + + public void setHeader(String name, String value) { + headers.put(name, value); + } + + public void clearHeader(String name) { + headers.remove(name); + } + + public MethodResponse execute(MethodCall methodCall) throws IOException, + ParserConfigurationException, SAXException, MySQLFabricException { + HttpURLConnection connection = null; + try { + connection = (HttpURLConnection) this.url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("User-Agent", "MySQL XML-RPC"); + connection.setRequestProperty("Content-Type", "text/xml"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + + // apply headers + for (Map.Entry entry : headers.entrySet()) { + connection.setRequestProperty(entry.getKey(), entry.getValue()); + } + + String out = methodCall.toString(); + + // Send request + OutputStream os = connection.getOutputStream(); + os.write(out.getBytes()); + os.flush(); + os.close(); + + // Get Response + InputStream is = connection.getInputStream(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser parser = factory.newSAXParser(); + ResponseParser saxp = new ResponseParser(); + + parser.parse(is, saxp); + + is.close(); + + MethodResponse resp = saxp.getMethodResponse(); + if (resp.getFault() != null) { + throw new MySQLFabricException(resp.getFault()); + } + + return resp; + + } finally { + if (connection != null) { + connection.disconnect(); + } + } + + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Array.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Array.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Array.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,58 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +public class Array { + + protected Data data; + + /** + * Gets the value of the data property. + */ + public Data getData() { + return data; + } + + /** + * Sets the value of the data property. + */ + public void setData(Data value) { + this.data = value; + } + + public void addValue(Value v) { + if (this.data == null) { + this.data = new Data(); + } + this.data.addValue(v); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(""); + sb.append(this.data.toString()); + sb.append(""); + return sb.toString(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Data.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Data.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Data.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,56 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +import java.util.ArrayList; +import java.util.List; + +public class Data { + + protected List value; + + public List getValue() { + if (value == null) { + value = new ArrayList(); + } + return this.value; + } + + public void addValue(Value v) { + getValue().add(v); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + if (this.value != null) { + sb.append(""); + for (int i = 0; i < this.value.size(); i++) { + sb.append(this.value.get(i).toString()); + } + sb.append(""); + } + return sb.toString(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Fault.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Fault.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Fault.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,53 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +public class Fault { + + protected Value value; + + /** + * Gets the value of the value property. + */ + public Value getValue() { + return value; + } + + /** + * Sets the value of the value property. + */ + public void setValue(Value value) { + this.value = value; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + if (this.value != null) { + sb.append(""); + sb.append(this.value.toString()); + sb.append(""); + } + return sb.toString(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Member.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Member.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Member.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,75 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +public class Member { + + protected String name; + protected Value value; + + public Member() { + } + + public Member(String name, Value value) { + setName(name); + setValue(value); + } + + /** + * Gets the value of the name property. + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the value property. + */ + public Value getValue() { + return value; + } + + /** + * Sets the value of the value property. + */ + public void setValue(Value value) { + this.value = value; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(""); + sb.append("" + this.name + ""); + sb.append(this.value.toString()); + sb.append(""); + return sb.toString(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/MethodCall.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/MethodCall.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/MethodCall.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,71 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +public class MethodCall { + + protected String methodName; + protected Params params; + + /** + * Gets the value of the methodName property. + */ + public String getMethodName() { + return methodName; + } + + /** + * Sets the value of the methodName property. + */ + public void setMethodName(String value) { + this.methodName = value; + } + + /** + * Gets the value of the params property. + */ + public Params getParams() { + return params; + } + + /** + * Sets the value of the params property. + */ + public void setParams(Params value) { + this.params = value; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(""); + sb.append(""); + sb.append(" " + this.methodName + ""); + if (this.params != null) { + sb.append(this.params.toString()); + } + sb.append(""); + return sb.toString(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/MethodResponse.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/MethodResponse.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/MethodResponse.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,74 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +public class MethodResponse { + + protected Params params; + protected Fault fault; + + /** + * Gets the value of the params property. + */ + public Params getParams() { + return params; + } + + /** + * Sets the value of the params property. + */ + public void setParams(Params value) { + this.params = value; + } + + /** + * Gets the value of the fault property. + * + */ + public Fault getFault() { + return fault; + } + + /** + * Sets the value of the fault property. + */ + public void setFault(Fault value) { + this.fault = value; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(""); + sb.append(""); + if (this.params != null) { + sb.append(this.params.toString()); + } + if (this.fault != null) { + sb.append(this.fault.toString()); + } + sb.append(""); + return sb.toString(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Param.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Param.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Param.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,59 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +public class Param { + + protected Value value; + + public Param() { + } + + public Param(Value value) { + this.value = value; + } + + /** + * Gets the value of the value property. + */ + public Value getValue() { + return value; + } + + /** + * Sets the value of the value property. + */ + public void setValue(Value value) { + this.value = value; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(""); + sb.append(this.value.toString()); + sb.append(""); + return sb.toString(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Params.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Params.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Params.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,56 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +import java.util.ArrayList; +import java.util.List; + +public class Params { + + protected List param; + + public List getParam() { + if (param == null) { + param = new ArrayList(); + } + return this.param; + } + + public void addParam(Param p) { + getParam().add(p); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + if (this.param != null) { + sb.append(""); + for (int i = 0; i < this.param.size(); i++) { + sb.append(this.param.get(i).toString()); + } + sb.append(""); + } + return sb.toString(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/ResponseParser.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/ResponseParser.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/ResponseParser.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,155 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +import java.util.Stack; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +public class ResponseParser extends DefaultHandler { + + private MethodResponse resp = null; + + public MethodResponse getMethodResponse() { + return resp; + } + + Stack elNames = new Stack(); + Stack objects = new Stack(); + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + + String thisElement = qName; + if (thisElement != null) { + elNames.push(thisElement); + + if (thisElement.equals("methodResponse")) { + objects.push(new MethodResponse()); + } else if (thisElement.equals("params")) { + objects.push(new Params()); + } else if (thisElement.equals("param")) { + objects.push(new Param()); + } else if (thisElement.equals("value")) { + objects.push(new Value()); + } else if (thisElement.equals("array")) { + objects.push(new Array()); + } else if (thisElement.equals("data")) { + objects.push(new Data()); + } else if (thisElement.equals("struct")) { + objects.push(new Struct()); + } else if (thisElement.equals("member")) { + objects.push(new Member()); + } else if (thisElement.equals("fault")) { + objects.push(new Fault()); + } + } + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + String thisElement = (String) elNames.pop(); + if (thisElement != null) { + if (thisElement.equals("methodResponse")) { + this.resp = (MethodResponse) objects.pop(); + } else if (thisElement.equals("params")) { + Params pms = (Params) objects.pop(); + MethodResponse parent = (MethodResponse) objects.peek(); + parent.setParams(pms); + } else if (thisElement.equals("param")) { + Param p = (Param) objects.pop(); + Params parent = (Params) objects.peek(); + parent.addParam(p); + } else if (thisElement.equals("value")) { + Value v = (Value) objects.pop(); + Object parent = objects.peek(); + if (parent instanceof Data) { + ((Data) parent).addValue(v); + } else if (parent instanceof Param) { + ((Param) parent).setValue(v); + } else if (parent instanceof Member) { + ((Member) parent).setValue(v); + } else if (parent instanceof Fault) { + ((Fault) parent).setValue(v); + } + } else if (thisElement.equals("array")) { + Array a = (Array) objects.pop(); + Value parent = (Value) objects.peek(); + parent.setArray(a); + } else if (thisElement.equals("data")) { + Data d = (Data) objects.pop(); + Array parent = (Array) objects.peek(); + parent.setData(d); + } else if (thisElement.equals("struct")) { + Struct s = (Struct) objects.pop(); + Value parent = (Value) objects.peek(); + parent.setStruct(s); + } else if (thisElement.equals("member")) { + Member m = (Member) objects.pop(); + Struct parent = (Struct) objects.peek(); + parent.addMember(m); + } else if (thisElement.equals("fault")) { + Fault f = (Fault) objects.pop(); + MethodResponse parent = (MethodResponse) objects.peek(); + parent.setFault(f); + } + } + } + + @Override + public void characters(char[] ch, int start, int length) + throws SAXException { + try { + String thisElement = (String) elNames.peek(); + if (thisElement != null) { + if (thisElement.equals("name")) { + ((Member) objects.peek()).setName(new String(ch, start, length)); + } else if (thisElement.equals("value")) { + ((Value) objects.peek()).appendString(new String(ch, start, length)); + } else if (thisElement.equals("i4") + || thisElement.equals("int")) { + ((Value) objects.peek()).setInt(new String(ch, start, length)); + } else if (thisElement.equals("boolean")) { + ((Value) objects.peek()).setBoolean(new String(ch, start, length)); + } else if (thisElement.equals("string")) { + ((Value) objects.peek()).appendString(new String(ch, start, length)); + } else if (thisElement.equals("double")) { + ((Value) objects.peek()).setDouble(new String(ch, start, length)); + } else if (thisElement.equals("dateTime.iso8601")) { + ((Value) objects.peek()).setDateTime(new String(ch, start, length)); + } else if (thisElement.equals("base64")) { + ((Value) objects.peek()).setBase64(new String(ch, start, length).getBytes()); + } + } + } catch (Exception e) { + throw new SAXParseException(e.getMessage(), null, e); + } + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Struct.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Struct.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Struct.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,56 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +import java.util.ArrayList; +import java.util.List; + +public class Struct { + + protected List member; + + public List getMember() { + if (member == null) { + member = new ArrayList(); + } + return this.member; + } + + public void addMember(Member m) { + getMember().add(m); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + if (this.member != null) { + sb.append(""); + for (int i = 0; i < this.member.size(); i++) { + sb.append(this.member.get(i).toString()); + } + sb.append(""); + } + return sb.toString(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Value.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Value.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/base/Value.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,235 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.base; + +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +public class Value { + + public static final byte TYPE_i4 = 0; + public static final byte TYPE_int = 1; + public static final byte TYPE_boolean = 2; + public static final byte TYPE_string = 3; + public static final byte TYPE_double = 4; + public static final byte TYPE_dateTime_iso8601 = 5; + public static final byte TYPE_base64 = 6; + public static final byte TYPE_struct = 7; + public static final byte TYPE_array = 8; + + protected Object objValue = ""; + protected byte objType = TYPE_string; + private DatatypeFactory dtf = null; + + public Value() { + } + + public Value(int value) { + setInt(value); + } + + public Value(String value) { + setString(value); + } + + public Value(boolean value) { + setBoolean(value); + } + + public Value(double value) { + setDouble(value); + } + + public Value(GregorianCalendar value) throws DatatypeConfigurationException { + setDateTime(value); + } + + public Value(byte[] value) { + setBase64(value); + } + + public Value(Struct value) { + setStruct(value); + } + + public Value(Array value) { + setArray(value); + } + + public Object getValue() { + return this.objValue; + } + + public byte getType() { + return this.objType; + } + + public void setInt(int value) { + this.objValue = Integer.valueOf(value); + this.objType = TYPE_int; + } + + public void setInt(String value) { + this.objValue = Integer.valueOf(value); + this.objType = TYPE_int; + } + + public void setString(String value) { + this.objValue = value; + this.objType = TYPE_string; + } + + public void appendString(String value) { + this.objValue = this.objValue != null ? this.objValue + value : value; + this.objType = TYPE_string; + } + + public void setBoolean(boolean value) { + this.objValue = Boolean.valueOf(value); + this.objType = TYPE_boolean; + } + + public void setBoolean(String value) { + if (value.trim().equals("1") || value.trim().equalsIgnoreCase("true")) { + this.objValue = true; + } else { + this.objValue = false; + } + this.objType = TYPE_boolean; + } + + public void setDouble(double value) { + this.objValue = Double.valueOf(value); + this.objType = TYPE_double; + } + + public void setDouble(String value) { + this.objValue = Double.valueOf(value); + this.objType = TYPE_double; + } + + public void setDateTime(GregorianCalendar value) + throws DatatypeConfigurationException { + if (this.dtf == null) { + dtf = DatatypeFactory.newInstance(); + } + this.objValue = dtf.newXMLGregorianCalendar(value); + this.objType = TYPE_dateTime_iso8601; + } + + public void setDateTime(String value) throws DatatypeConfigurationException { + if (this.dtf == null) { + dtf = DatatypeFactory.newInstance(); + } + this.objValue = dtf.newXMLGregorianCalendar(value); + this.objType = TYPE_dateTime_iso8601; + } + + public void setBase64(byte[] value) { + this.objValue = value; + this.objType = TYPE_base64; + } + + public void setStruct(Struct value) { + this.objValue = value; + this.objType = TYPE_struct; + } + + public void setArray(Array value) { + this.objValue = value; + this.objType = TYPE_array; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(""); + switch (this.objType) { + case Value.TYPE_i4: + sb.append("" + ((Integer) objValue).toString() + ""); + break; + case Value.TYPE_int: + sb.append("" + ((Integer) objValue).toString() + ""); + break; + + case Value.TYPE_boolean: + sb.append("" + (((Boolean) objValue) ? 1 : 0) + + ""); + break; + + case Value.TYPE_double: + sb.append("" + ((Double) objValue).toString() + ""); + break; + + case Value.TYPE_dateTime_iso8601: + sb.append("" + + ((XMLGregorianCalendar) objValue).toString() + + ""); + break; + + case Value.TYPE_base64: + sb.append("" + ((byte[]) objValue).toString() + ""); + break; + + case Value.TYPE_struct: + sb.append(((Struct) objValue).toString()); + break; + + case Value.TYPE_array: + sb.append(((Array) objValue).toString()); + break; + + default: + sb.append("" + escapeXMLChars(objValue.toString()) + + ""); + } + sb.append(""); + return sb.toString(); + } + + private String escapeXMLChars(String s) { + StringBuffer sb = new StringBuffer(s.length()); + char c; + for (int i = 0; i < s.length(); i++) { + c = s.charAt(i); + switch (c) { + case '&': + sb.append("&"); + break; + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + default: + sb.append(c); + break; + } + } + return sb.toString(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/exceptions/MySQLFabricException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/exceptions/MySQLFabricException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/fabric/xmlrpc/exceptions/MySQLFabricException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,57 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.fabric.xmlrpc.exceptions; + +import java.sql.SQLException; + +import com.mysql.fabric.xmlrpc.base.Fault; +import com.mysql.fabric.xmlrpc.base.Struct; + +public class MySQLFabricException extends SQLException { + + static final long serialVersionUID = -8776763137552613517L; + + public MySQLFabricException() { + super(); + } + + public MySQLFabricException(Fault fault) { + super( + (String)((Struct)fault.getValue().getValue()).getMember().get(1).getValue().getValue(), + "", + (Integer)((Struct)fault.getValue().getValue()).getMember().get(0).getValue().getValue()); + } + + public MySQLFabricException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLFabricException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLFabricException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/AbandonedConnectionCleanupThread.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/AbandonedConnectionCleanupThread.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/AbandonedConnectionCleanupThread.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,65 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.lang.ref.Reference; +import com.mysql.jdbc.NonRegisteringDriver.ConnectionPhantomReference; + +public class AbandonedConnectionCleanupThread extends Thread { + private static boolean running = true; + private static Thread threadRef = null; + + public AbandonedConnectionCleanupThread() { + super("Abandoned connection cleanup thread"); + } + + public void run() { + threadRef = this; + while (running) { + try { + Reference ref = NonRegisteringDriver.refQueue.remove(100); + if (ref != null) { + try { + ((ConnectionPhantomReference) ref).cleanup(); + } finally { + NonRegisteringDriver.connectionPhantomRefs.remove(ref); + } + } + + } catch (Exception ex) { + // no where to really log this if we're static + } + } + } + + public static void shutdown() throws InterruptedException { + running = false; + if (threadRef != null) { + threadRef.interrupt(); + threadRef.join(); + threadRef = null; + } + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/AssertionFailedException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/AssertionFailedException.java (.../AssertionFailedException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/AssertionFailedException.java (.../AssertionFailedException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -33,9 +32,13 @@ * mmatthews Exp $ */ public class AssertionFailedException extends RuntimeException { + + private static final long serialVersionUID = 1L; + // ~ Constructors // ----------------------------------------------------------- + /** * Convenience method. * Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/AuthenticationPlugin.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/AuthenticationPlugin.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/AuthenticationPlugin.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,119 @@ +/* + Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.List; + +/** + * Implementors of this interface can be installed via the + * "authenticationPlugins" configuration property. + * + * The driver will create one instance of a given plugin per {@link MysqlIO} + * instance if it's reusable (see {@link #isReusable()}) or a new instance + * in each {@link + * MysqlIO#proceedHandshakeWithPluggableAuthentication(String, String, + * String, Buffer)} call. + */ +public interface AuthenticationPlugin extends Extension { + + /** + * Returns the name that the MySQL server uses on + * the wire for this plugin + * @return + */ + String getProtocolPluginName(); + + /** + * Does this plugin require the connection itself to be confidential + * (i.e. tls/ssl)...Highly recommended to return "true" for plugins + * that return the credentials in the clear. + * @return + */ + boolean requiresConfidentiality(); + + /** + * + * @return true if plugin instance may be reused, false otherwise + */ + boolean isReusable(); + + /** + * This method called from cJ before first nextAuthenticationStep + * call. Values of user and password parameters are passed from + * those in MysqlIO.changeUser(String userName, String password, + * String database) or MysqlIO.doHandshake(String user, String + * password, String database). + * + * Plugin should use these values instead of values from connection + * properties because parent method may be a changeUser call which + * saves user and password into connection only after successful + * handshake. + * + * @param user + * @param password + */ + void setAuthenticationParameters(String user, String password); + + /** + * Process authentication handshake data from server and optionally + * produce data to be sent back to the server. The driver will keep + * calling this method until either a SQLException is thrown + * (authentication failure, please use appropriate SQLStates) or the + * method returns false or driver receives an OK packet from the server + * which indicates that the connection has been already approved. + * + * If, on return from this method, toServer is a non-empty list of + * buffers, then these buffers should be sent to the server in order and + * without any reads in between them. If toServer is an empty list, no + * data should be sent to server. + * + * If method returns true, it means that this plugin does not need any + * more data from the server to conclude the handshake and this method + * should not be called again. (Note that server can send an Auth Method + * Switch request and then another handshake will start, possibly using a + * different plugin.) + * + * If this method returns false, it means that plugin needs more data from + * the server to conclude the handshake. In that case next handshake data + * payload should be read from the server (after possibly writing data + * from toServer as explained above). Then this method should be called + * again with the new data in fromServer parameter. + * + * In case of errors the method should throw SQLException with appropriate + * SQLStates. + * + * @param fromServer a buffer containing handshake data payload from + * server (can be empty). + * @param toServer list of buffers with data to be sent to the server + * (the list can be empty, but buffers in the list + * should contain data). + * + * @return False if more data should be read from the server and next call + * to this method made, true otherwise. + */ + boolean nextAuthenticationStep(Buffer fromServer, List toServer) + throws SQLException; + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/BalanceStrategy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/BalanceStrategy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/BalanceStrategy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,78 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * Implement this interface to provide a new load balancing strategy for URLs of + * the form "jdbc:mysql:loadbalance://..", and provide the implementation class + * name as the configuration parameter "loadBalanceStrategy". + * + * The driver will not pass in a Connection instance when calling init(), but it + * will pass in the Properties, otherwise it acts like a normal Extension. + * + * One instance of a strategy *per* JDBC connection instance will be created. If + * you need singleton-like behavior, you're on your own to provide it. + */ +public interface BalanceStrategy extends Extension { + /** + * Called by the driver to pick a new connection to route requests over. + * + * @param proxy + * the InvocationHandler that deals with actual method calls to + * the JDBC connection, and serves as a factory for new + * connections for this strategy via the + * createConnectionForHost() method. + * + * This proxy takes care of maintaining the response time list, map of + * host/ports to live connections, and taking connections out of the live + * connections map if they receive a network-related error while they are in + * use by the application. + * @param configuredHosts + * the list of hosts/ports (in "host:port" form) as passed in by + * the user. + * @param liveConnections + * a map of host/ports to "live" connections to them. + * @param responseTimes + * the list of response times for a transaction + * for each host in the configured hosts list. + * @param numRetries + * the number of times the driver expects this strategy to re-try + * connection attempts if creating a new connection fails. + * @return the physical JDBC connection for the application to use, based + * upon the strategy employed. + * @throws SQLException + * if a new connection can not be found or created by this + * strategy. + * + * @see LoadBalancingConnectionProxy#createConnectionForHost(String) + */ + public abstract ConnectionImpl pickConnection( + LoadBalancingConnectionProxy proxy, List configuredHosts, + Map liveConnections, long[] responseTimes, int numRetries) + throws SQLException; +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/BestResponseTimeBalanceStrategy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/BestResponseTimeBalanceStrategy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/BestResponseTimeBalanceStrategy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,121 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +public class BestResponseTimeBalanceStrategy implements BalanceStrategy { + + /** + * @param loadBalancingConnectionProxy + */ + public BestResponseTimeBalanceStrategy() { + } + + public void destroy() { + // we don't have anything to clean up + } + + public void init(Connection conn, Properties props) throws SQLException { + // we don't have anything to initialize + } + + public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, + List configuredHosts, Map liveConnections, long[] responseTimes, + int numRetries) throws SQLException { + + Map blackList = proxy.getGlobalBlacklist(); + + SQLException ex = null; + + for (int attempts = 0; attempts < numRetries; ) { + long minResponseTime = Long.MAX_VALUE; + + int bestHostIndex = 0; + + // safety + if (blackList.size() == configuredHosts.size()) { + blackList = proxy.getGlobalBlacklist(); + } + + for (int i = 0; i < responseTimes.length; i++) { + long candidateResponseTime = responseTimes[i]; + + if (candidateResponseTime < minResponseTime + && !blackList.containsKey(configuredHosts.get(i))) { + if (candidateResponseTime == 0) { + bestHostIndex = i; + + break; + } + + bestHostIndex = i; + minResponseTime = candidateResponseTime; + } + } + + String bestHost = configuredHosts.get(bestHostIndex); + + ConnectionImpl conn = liveConnections.get(bestHost); + + if (conn == null) { + try { + conn = proxy.createConnectionForHost(bestHost); + } catch (SQLException sqlEx) { + ex = sqlEx; + + if (proxy.shouldExceptionTriggerFailover(sqlEx)) { + proxy.addToGlobalBlacklist(bestHost); + blackList.put(bestHost, null); + + + if (blackList.size() == configuredHosts.size()) { + attempts++; + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + blackList = proxy.getGlobalBlacklist(); // try again after a little bit + } + + continue; + } + + throw sqlEx; + } + } + + return conn; + } + + if (ex != null) { + throw ex; + } + + return null; // we won't get here, compiler can't tell + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Blob.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Blob.java (.../Blob.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Blob.java (.../Blob.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,33 +1,32 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; - import java.sql.SQLException; /** @@ -57,15 +56,26 @@ /** The binary data that makes up this BLOB */ private byte[] binaryData = null; - + private boolean isClosed = false; + private ExceptionInterceptor exceptionInterceptor; + /** + * Creates a Blob without data + */ + Blob(ExceptionInterceptor exceptionInterceptor) { + setBinaryData(Constants.EMPTY_BYTE_ARRAY); + this.exceptionInterceptor = exceptionInterceptor; + } + + /** * Creates a BLOB encapsulating the given binary data * * @param data * DOCUMENT ME! */ - Blob(byte[] data) { + Blob(byte[] data, ExceptionInterceptor exceptionInterceptor) { setBinaryData(data); + this.exceptionInterceptor = exceptionInterceptor; } /** @@ -78,11 +88,11 @@ * @param columnIndexToSet * DOCUMENT ME! */ - Blob(byte[] data, ResultSet creatorResultSetToSet, int columnIndexToSet) { + Blob(byte[] data, ResultSetInternalMethods creatorResultSetToSet, int columnIndexToSet) { setBinaryData(data); } - private byte[] getBinaryData() { + private synchronized byte[] getBinaryData() { return this.binaryData; } @@ -94,7 +104,9 @@ * @throws SQLException * if a database error occurs */ - public java.io.InputStream getBinaryStream() throws SQLException { + public synchronized java.io.InputStream getBinaryStream() throws SQLException { + checkClosed(); + return new ByteArrayInputStream(getBinaryData()); } @@ -113,14 +125,28 @@ * @throws SQLException * if a database error occurs */ - public byte[] getBytes(long pos, int length) throws SQLException { + public synchronized byte[] getBytes(long pos, int length) throws SQLException { + checkClosed(); + if (pos < 1) { throw SQLError.createSQLException(Messages.getString("Blob.2"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } + pos--; + + if (pos > this.binaryData.length) { + throw SQLError.createSQLException("\"pos\" argument can not be larger than the BLOB's length.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + if (pos + length > this.binaryData.length) { + throw SQLError.createSQLException("\"pos\" + \"length\" arguments can not be larger than the BLOB's length.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + byte[] newData = new byte[length]; - System.arraycopy(getBinaryData(), (int) (pos - 1), newData, 0, length); + System.arraycopy(getBinaryData(), (int) (pos), newData, 0, length); return newData; } @@ -134,15 +160,17 @@ * @throws SQLException * if a database error occurs */ - public long length() throws SQLException { + public synchronized long length() throws SQLException { + checkClosed(); + return getBinaryData().length; } /** * @see java.sql.Blob#position(byte[], long) */ - public long position(byte[] pattern, long start) throws SQLException { - throw SQLError.createSQLException("Not implemented"); //$NON-NLS-1$ + public synchronized long position(byte[] pattern, long start) throws SQLException { + throw SQLError.createSQLException("Not implemented", this.exceptionInterceptor); //$NON-NLS-1$ } /** @@ -159,22 +187,26 @@ * @throws SQLException * if a database error occurs */ - public long position(java.sql.Blob pattern, long start) throws SQLException { + public synchronized long position(java.sql.Blob pattern, long start) throws SQLException { + checkClosed(); + return position(pattern.getBytes(0, (int) pattern.length()), start); } - private void setBinaryData(byte[] newBinaryData) { + private synchronized void setBinaryData(byte[] newBinaryData) { this.binaryData = newBinaryData; } /** * @see Blob#setBinaryStream(long) */ - public OutputStream setBinaryStream(long indexToWriteAt) + public synchronized OutputStream setBinaryStream(long indexToWriteAt) throws SQLException { + checkClosed(); + if (indexToWriteAt < 1) { throw SQLError.createSQLException(Messages.getString("Blob.0"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } WatchableOutputStream bytesOut = new WatchableOutputStream(); @@ -190,22 +222,29 @@ /** * @see Blob#setBytes(long, byte[]) */ - public int setBytes(long writeAt, byte[] bytes) throws SQLException { + public synchronized int setBytes(long writeAt, byte[] bytes) throws SQLException { + checkClosed(); + return setBytes(writeAt, bytes, 0, bytes.length); } /** * @see Blob#setBytes(long, byte[], int, int) */ - public int setBytes(long writeAt, byte[] bytes, int offset, int length) + public synchronized int setBytes(long writeAt, byte[] bytes, int offset, int length) throws SQLException { + checkClosed(); + OutputStream bytesOut = setBinaryStream(writeAt); try { bytesOut.write(bytes, offset, length); } catch (IOException ioEx) { - throw SQLError.createSQLException(Messages.getString("Blob.1"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLException sqlEx = SQLError.createSQLException(Messages.getString("Blob.1"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + sqlEx.initCause(ioEx); + + throw sqlEx; } finally { try { bytesOut.close(); @@ -220,14 +259,14 @@ /** * @see com.mysql.jdbc.OutputStreamWatcher#streamClosed(byte[]) */ - public void streamClosed(byte[] byteData) { + public synchronized void streamClosed(byte[] byteData) { this.binaryData = byteData; } /** * @see com.mysql.jdbc.OutputStreamWatcher#streamClosed(byte[]) */ - public void streamClosed(WatchableOutputStream out) { + public synchronized void streamClosed(WatchableOutputStream out) { int streamSize = out.size(); if (streamSize < this.binaryData.length) { @@ -239,9 +278,110 @@ } /** - * @see Blob#truncate(long) - */ - public void truncate(long arg0) throws SQLException { - throw new NotImplemented(); + * Truncates the BLOB value that this Blob + * object represents to be len bytes in length. + *

+ * Note: If the value specified for len + * is greater then the length+1 of the BLOB value then the + * behavior is undefined. Some JDBC drivers may throw a + * SQLException while other drivers may support this + * operation. + * + * @param len the length, in bytes, to which the BLOB value + * that this Blob object represents should be truncated + * @exception SQLException if there is an error accessing the + * BLOB value or if len is less than 0 + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * @since 1.4 + */ + public synchronized void truncate(long len) throws SQLException { + checkClosed(); + + if (len < 0) { + throw SQLError.createSQLException("\"len\" argument can not be < 1.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + if (len > this.binaryData.length) { + throw SQLError.createSQLException("\"len\" argument can not be larger than the BLOB's length.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + // TODO: Do this without copying byte[]s by maintaining some end pointer + // on the original data + + byte[] newData = new byte[(int)len]; + System.arraycopy(getBinaryData(), 0, newData, 0, (int)len); + this.binaryData = newData; } + + /** + * This method frees the Blob object and releases the resources that + * it holds. The object is invalid once the free + * method is called. + *

+ * After free has been called, any attempt to invoke a + * method other than free will result in a SQLException + * being thrown. If free is called multiple times, the subsequent + * calls to free are treated as a no-op. + *

+ * + * @throws SQLException if an error occurs releasing + * the Blob's resources + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * @since 1.6 + */ + + public synchronized void free() throws SQLException { + this.binaryData = null; + this.isClosed = true; + } + + /** + * Returns an InputStream object that contains a partial Blob value, + * starting with the byte specified by pos, which is length bytes in length. + * + * @param pos the offset to the first byte of the partial value to be retrieved. + * The first byte in the Blob is at position 1 + * @param length the length in bytes of the partial value to be retrieved + * @return InputStream through which the partial Blob value can be read. + * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes + * in the Blob or if pos + length is greater than the number of bytes + * in the Blob + * + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * @since 1.6 + */ + public synchronized InputStream getBinaryStream(long pos, long length) throws SQLException { + checkClosed(); + + if (pos < 1) { + throw SQLError.createSQLException("\"pos\" argument can not be < 1.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + pos--; + + if (pos > this.binaryData.length) { + throw SQLError.createSQLException("\"pos\" argument can not be larger than the BLOB's length.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + if (pos + length > this.binaryData.length) { + throw SQLError.createSQLException("\"pos\" + \"length\" arguments can not be larger than the BLOB's length.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + return new ByteArrayInputStream(getBinaryData(), (int)pos, (int)length); + } + + private synchronized void checkClosed() throws SQLException { + if (this.isClosed) { + throw SQLError.createSQLException("Invalid operation on closed BLOB", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/BlobFromLocator.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/BlobFromLocator.java (.../BlobFromLocator.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/BlobFromLocator.java (.../BlobFromLocator.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.BufferedInputStream; @@ -52,12 +51,12 @@ * Exp $ */ public class BlobFromLocator implements java.sql.Blob { - private List primaryKeyColumns = null; + private List primaryKeyColumns = null; - private List primaryKeyValues = null; + private List primaryKeyValues = null; /** The ResultSet that created this BLOB */ - private ResultSet creatorResultSet; + private ResultSetImpl creatorResultSet; private String blobColumnName = null; @@ -69,20 +68,23 @@ private String quotedId; + private ExceptionInterceptor exceptionInterceptor; + /** * Creates an updatable BLOB that can update in-place */ - BlobFromLocator(ResultSet creatorResultSetToSet, int blobColumnIndex) + BlobFromLocator(ResultSetImpl creatorResultSetToSet, int blobColumnIndex, ExceptionInterceptor exceptionInterceptor) throws SQLException { + this.exceptionInterceptor = exceptionInterceptor; this.creatorResultSet = creatorResultSetToSet; this.numColsInResultSet = this.creatorResultSet.fields.length; this.quotedId = this.creatorResultSet.connection.getMetaData() .getIdentifierQuoteString(); if (this.numColsInResultSet > 1) { - this.primaryKeyColumns = new ArrayList(); - this.primaryKeyValues = new ArrayList(); + this.primaryKeyColumns = new ArrayList(); + this.primaryKeyValues = new ArrayList(); for (int i = 0; i < this.numColsInResultSet; i++) { if (this.creatorResultSet.fields[i].isPrimaryKey()) { @@ -154,15 +156,15 @@ private void notEnoughInformationInQuery() throws SQLException { throw SQLError.createSQLException("Emulated BLOB locators must come from " + "a ResultSet with only one table selected, and all primary " - + "keys selected", SQLError.SQL_STATE_GENERAL_ERROR); + + "keys selected", SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } /** * @see Blob#setBinaryStream(long) */ public OutputStream setBinaryStream(long indexToWriteAt) throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** @@ -206,12 +208,12 @@ query.append(length); query.append(", ?) WHERE "); - query.append((String) this.primaryKeyColumns.get(0)); + query.append(this.primaryKeyColumns.get(0)); query.append(" = ?"); for (int i = 1; i < this.numPrimaryKeys; i++) { query.append(" AND "); - query.append((String) this.primaryKeyColumns.get(i)); + query.append(this.primaryKeyColumns.get(i)); query.append(" = ?"); } @@ -223,15 +225,15 @@ pStmt.setBytes(1, bytesToWrite); for (int i = 0; i < this.numPrimaryKeys; i++) { - pStmt.setString(i + 2, (String) this.primaryKeyValues.get(i)); + pStmt.setString(i + 2, this.primaryKeyValues.get(i)); } int rowsUpdated = pStmt.executeUpdate(); if (rowsUpdated != 1) { throw SQLError.createSQLException( "BLOB data not found! Did primary keys change?", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } finally { if (pStmt != null) { @@ -290,7 +292,7 @@ } } } - + /** * Returns the number of bytes in the BLOB value designated by this Blob * object. @@ -311,12 +313,12 @@ query.append(this.tableName); query.append(" WHERE "); - query.append((String) this.primaryKeyColumns.get(0)); + query.append(this.primaryKeyColumns.get(0)); query.append(" = ?"); for (int i = 1; i < this.numPrimaryKeys; i++) { query.append(" AND "); - query.append((String) this.primaryKeyColumns.get(i)); + query.append(this.primaryKeyColumns.get(i)); query.append(" = ?"); } @@ -326,7 +328,7 @@ .toString()); for (int i = 0; i < this.numPrimaryKeys; i++) { - pStmt.setString(i + 1, (String) this.primaryKeyValues.get(i)); + pStmt.setString(i + 1, this.primaryKeyValues.get(i)); } blobRs = pStmt.executeQuery(); @@ -337,7 +339,7 @@ throw SQLError.createSQLException( "BLOB data not found! Did primary keys change?", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } finally { if (blobRs != null) { try { @@ -396,12 +398,12 @@ query.append(this.tableName); query.append(" WHERE "); - query.append((String) this.primaryKeyColumns.get(0)); + query.append(this.primaryKeyColumns.get(0)); query.append(" = ?"); for (int i = 1; i < this.numPrimaryKeys; i++) { query.append(" AND "); - query.append((String) this.primaryKeyColumns.get(i)); + query.append(this.primaryKeyColumns.get(i)); query.append(" = ?"); } @@ -412,7 +414,7 @@ pStmt.setBytes(1, pattern); for (int i = 0; i < this.numPrimaryKeys; i++) { - pStmt.setString(i + 2, (String) this.primaryKeyValues.get(i)); + pStmt.setString(i + 2, this.primaryKeyValues.get(i)); } blobRs = pStmt.executeQuery(); @@ -423,7 +425,7 @@ throw SQLError.createSQLException( "BLOB data not found! Did primary keys change?", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } finally { if (blobRs != null) { try { @@ -464,12 +466,12 @@ query.append(length); query.append(") WHERE "); - query.append((String) this.primaryKeyColumns.get(0)); + query.append(this.primaryKeyColumns.get(0)); query.append(" = ?"); for (int i = 1; i < this.numPrimaryKeys; i++) { query.append(" AND "); - query.append((String) this.primaryKeyColumns.get(i)); + query.append(this.primaryKeyColumns.get(i)); query.append(" = ?"); } @@ -479,15 +481,15 @@ .toString()); for (int i = 0; i < this.numPrimaryKeys; i++) { - pStmt.setString(i + 1, (String) this.primaryKeyValues.get(i)); + pStmt.setString(i + 1, this.primaryKeyValues.get(i)); } int rowsUpdated = pStmt.executeUpdate(); if (rowsUpdated != 1) { throw SQLError.createSQLException( "BLOB data not found! Did primary keys change?", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } finally { if (pStmt != null) { @@ -514,12 +516,12 @@ query.append(this.tableName); query.append(" WHERE "); - query.append((String) this.primaryKeyColumns.get(0)); + query.append(this.primaryKeyColumns.get(0)); query.append(" = ?"); for (int i = 1; i < this.numPrimaryKeys; i++) { query.append(" AND "); - query.append((String) this.primaryKeyColumns.get(i)); + query.append(this.primaryKeyColumns.get(i)); query.append(" = ?"); } @@ -538,18 +540,18 @@ pStmt.setInt(2, length); for (int i = 0; i < this.numPrimaryKeys; i++) { - pStmt.setString(i + 3, (String) this.primaryKeyValues.get(i)); + pStmt.setString(i + 3, this.primaryKeyValues.get(i)); } blobRs = pStmt.executeQuery(); if (blobRs.next()) { - return ((com.mysql.jdbc.ResultSet) blobRs).getBytes(1, true); + return ((com.mysql.jdbc.ResultSetImpl) blobRs).getBytes(1, true); } throw SQLError.createSQLException( "BLOB data not found! Did primary keys change?", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } finally { if (blobRs != null) { try { @@ -575,6 +577,30 @@ pStmt = createGetBytesStatement(); } + @SuppressWarnings("synthetic-access") + LocatorInputStream(long pos, long len) throws SQLException { + length = pos + len; + currentPositionInBlob = pos; + long blobLength = length(); + + if (pos + len > blobLength) { + throw SQLError.createSQLException( + Messages.getString("Blob.invalidStreamLength", + new Object[] {Long.valueOf(blobLength), Long.valueOf(pos), Long.valueOf(len)}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + + if (pos < 1) { + throw SQLError.createSQLException(Messages.getString("Blob.invalidStreamPos"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + + if (pos > blobLength) { + throw SQLError.createSQLException(Messages.getString("Blob.invalidStreamPos"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } + public int read() throws IOException { if (currentPositionInBlob + 1 > length) { return -1; @@ -667,4 +693,14 @@ super.close(); } } + + public void free() throws SQLException { + this.creatorResultSet = null; + this.primaryKeyColumns = null; + this.primaryKeyValues = null; + } + + public InputStream getBinaryStream(long pos, long length) throws SQLException { + return new LocatorInputStream(pos, length); + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Buffer.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Buffer.java (.../Buffer.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Buffer.java (.../Buffer.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,33 +1,30 @@ /* - Copyright (C) 2002-2005 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.UnsupportedEncodingException; - import java.nio.ByteBuffer; - import java.sql.SQLException; /** @@ -36,7 +33,7 @@ * @version $Id$ * @author Mark Matthews */ -class Buffer { +public class Buffer { static final int MAX_BYTES_TO_DUMP = 512; static final int NO_LENGTH_LIMIT = -1; @@ -51,7 +48,7 @@ protected boolean wasMultiPacket = false; - Buffer(byte[] buf) { + public Buffer(byte[] buf) { this.byteBuffer = buf; setBufLength(buf.length); } @@ -174,14 +171,24 @@ this.position += len; - return (int) len; // this is safe, as this is only + return (int) len; } + public void fastSkipLenByteArray() { + long len = this.readFieldLength(); + + if (len == NULL_LENGTH || len == 0) { + return; + } + + this.position += len; + } + protected final byte[] getBufferSource() { return this.byteBuffer; } - int getBufLength() { + public int getBufLength() { return this.bufLength; } @@ -237,6 +244,18 @@ return ((getBufLength() < 9) && ((this.byteBuffer[0] & 0xff) == 254)); } + final boolean isAuthMethodSwitchRequestPacket() { + return ((this.byteBuffer[0] & 0xff) == 254); + } + + final boolean isOKPacket() { + return ((this.byteBuffer[0] & 0xff) == 0); + } + + final boolean isRawPacket() { + return ((this.byteBuffer[0] & 0xff) == 1); + } + final long newReadLength() { int sw = this.byteBuffer[this.position++] & 0xff; @@ -398,7 +417,7 @@ // To avoid alloc'ing a new byte array, we // do this by hand, rather than calling getNullTerminatedBytes() // - final String readString() { + public final String readString() { int i = this.position; int len = 0; int maxLen = getBufLength(); @@ -408,13 +427,20 @@ i++; } - String s = new String(this.byteBuffer, this.position, len); + String s = StringUtils.toString(this.byteBuffer, this.position, len); this.position += (len + 1); // update cursor return s; } - final String readString(String encoding) throws SQLException { + /** + * Read string[NUL] + * @param encoding + * @param exceptionInterceptor + * @return + * @throws SQLException + */ + final String readString(String encoding, ExceptionInterceptor exceptionInterceptor) throws SQLException { int i = this.position; int len = 0; int maxLen = getBufLength(); @@ -425,16 +451,35 @@ } try { - return new String(this.byteBuffer, this.position, len, encoding); + return StringUtils.toString(this.byteBuffer, this.position, len, encoding); } catch (UnsupportedEncodingException uEE) { throw SQLError.createSQLException(Messages.getString("ByteArrayBuffer.1") //$NON-NLS-1$ - + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$ } finally { this.position += (len + 1); // update cursor } } - void setBufLength(int bufLengthToSet) { + /** + * Read string[$len] + */ + final String readString(String encoding, ExceptionInterceptor exceptionInterceptor, int expectedLength) throws SQLException { + if (this.position + expectedLength > getBufLength()) { + throw SQLError.createSQLException(Messages.getString("ByteArrayBuffer.2"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + + try { + return StringUtils.toString(this.byteBuffer, this.position, expectedLength, encoding); + } catch (UnsupportedEncodingException uEE) { + throw SQLError.createSQLException(Messages.getString("ByteArrayBuffer.1") //$NON-NLS-1$ + + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$ + } finally { + this.position += expectedLength; // update cursor + } + } + + public void setBufLength(int bufLengthToSet) { this.bufLength = bufLengthToSet; } @@ -485,14 +530,14 @@ return this.wasMultiPacket; } - final void writeByte(byte b) throws SQLException { + public final void writeByte(byte b) throws SQLException { ensureCapacity(1); this.byteBuffer[this.position++] = b; } // Write a byte array - final void writeBytesNoNull(byte[] bytes) throws SQLException { + public final void writeBytesNoNull(byte[] bytes) throws SQLException { int len = bytes.length; ensureCapacity(len); System.arraycopy(bytes, 0, this.byteBuffer, this.position, len); @@ -564,15 +609,15 @@ // encoding final void writeLenString(String s, String encoding, String serverEncoding, SingleByteCharsetConverter converter, boolean parserKnowsUnicode, - Connection conn) + MySQLConnection conn) throws UnsupportedEncodingException, SQLException { byte[] b = null; if (converter != null) { b = converter.toBytes(s); } else { b = StringUtils.getBytes(s, encoding, serverEncoding, - parserKnowsUnicode, conn); + parserKnowsUnicode, conn, conn.getExceptionInterceptor()); } int len = b.length; @@ -617,14 +662,14 @@ // Write null-terminated string final void writeString(String s) throws SQLException { - ensureCapacity((s.length() * 2) + 1); + ensureCapacity((s.length() * 3) + 1); writeStringNoNull(s); this.byteBuffer[this.position++] = 0; } // Write null-terminated string in the given encoding - final void writeString(String s, String encoding, Connection conn) throws SQLException { - ensureCapacity((s.length() * 2) + 1); + final void writeString(String s, String encoding, MySQLConnection conn) throws SQLException { + ensureCapacity((s.length() * 3) + 1); try { writeStringNoNull(s, encoding, encoding, false, conn); } catch (UnsupportedEncodingException ue) { @@ -637,8 +682,8 @@ // Write string, with no termination final void writeStringNoNull(String s) throws SQLException { int len = s.length(); - ensureCapacity(len * 2); - System.arraycopy(s.getBytes(), 0, this.byteBuffer, this.position, len); + ensureCapacity(len * 3); + System.arraycopy(StringUtils.getBytes(s), 0, this.byteBuffer, this.position, len); this.position += len; // for (int i = 0; i < len; i++) @@ -650,10 +695,10 @@ // Write a String using the specified character // encoding final void writeStringNoNull(String s, String encoding, - String serverEncoding, boolean parserKnowsUnicode, Connection conn) + String serverEncoding, boolean parserKnowsUnicode, MySQLConnection conn) throws UnsupportedEncodingException, SQLException { byte[] b = StringUtils.getBytes(s, encoding, serverEncoding, - parserKnowsUnicode, conn); + parserKnowsUnicode, conn, conn.getExceptionInterceptor()); int len = b.length; ensureCapacity(len); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/BufferRow.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/BufferRow.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/BufferRow.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,766 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.sql.Date; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.TimeZone; + +/** + * A RowHolder implementation that holds one row packet (which is re-used by the + * driver, and thus saves memory allocations), and tries when possible to avoid + * allocations to break out the results as individual byte[]s. + * + * (this isn't possible when doing things like reading floating point values). + * + * @version $Id$ + */ +public class BufferRow extends ResultSetRow { + private Buffer rowFromServer; + + /** + * The beginning of the row packet + */ + private int homePosition = 0; + + /** + * The home position before the is-null bitmask for server-side + * prepared statement result sets + */ + private int preNullBitmaskHomePosition = 0; + + /** + * The last-requested index, used as an optimization, if you ask for the + * same index, we won't seek to find it. If you ask for an index that is > + * than the last one requested, we start seeking from the last requested + * index. + */ + private int lastRequestedIndex = -1; + + /** + * The position of the last-requested index, optimization in concert with + * lastRequestedIndex. + */ + private int lastRequestedPos; + + /** + * The metadata of the fields of this result set. + */ + private Field[] metadata; + + /** + * Is this a row from a server-side prepared statement? If so, they're + * encoded differently, so we have different ways of finding where each + * column is, and unpacking them. + */ + private boolean isBinaryEncoded; + + /** + * If binary-encoded, the NULL status of each column is at the beginning of + * the row, so we + */ + private boolean[] isNull; + + private List openStreams; + + public BufferRow(Buffer buf, Field[] fields, boolean isBinaryEncoded, ExceptionInterceptor exceptionInterceptor) + throws SQLException { + super(exceptionInterceptor); + + this.rowFromServer = buf; + this.metadata = fields; + this.isBinaryEncoded = isBinaryEncoded; + this.homePosition = this.rowFromServer.getPosition(); + this.preNullBitmaskHomePosition = this.homePosition; + + if (fields != null) { + setMetadata(fields); + } + } + + public synchronized void closeOpenStreams() { + if (this.openStreams != null) { + // This would've looked slicker in a "for" loop + // but we want to skip over streams that fail to + // close (they probably won't ever) + // to be more robust and close everything we _can_ + + Iterator iter = this.openStreams.iterator(); + + while (iter.hasNext()) { + + try { + iter.next().close(); + } catch (IOException e) { + // ignore - it can't really happen in this case + } + } + + this.openStreams.clear(); + } + } + + private int findAndSeekToOffset(int index) throws SQLException { + if (!this.isBinaryEncoded) { + + if (index == 0) { + this.lastRequestedIndex = 0; + this.lastRequestedPos = this.homePosition; + this.rowFromServer.setPosition(this.homePosition); + + return 0; + } + + if (index == this.lastRequestedIndex) { + this.rowFromServer.setPosition(this.lastRequestedPos); + + return this.lastRequestedPos; + } + + int startingIndex = 0; + + if (index > this.lastRequestedIndex) { + if (this.lastRequestedIndex >= 0) { + startingIndex = this.lastRequestedIndex; + } else { + startingIndex = 0; + } + + this.rowFromServer.setPosition(this.lastRequestedPos); + } else { + this.rowFromServer.setPosition(this.homePosition); + } + + for (int i = startingIndex; i < index; i++) { + this.rowFromServer.fastSkipLenByteArray(); + } + + this.lastRequestedIndex = index; + this.lastRequestedPos = this.rowFromServer.getPosition(); + + return this.lastRequestedPos; + } + + return findAndSeekToOffsetForBinaryEncoding(index); + } + + private int findAndSeekToOffsetForBinaryEncoding(int index) + throws SQLException { + if (index == 0) { + this.lastRequestedIndex = 0; + this.lastRequestedPos = this.homePosition; + this.rowFromServer.setPosition(this.homePosition); + + return 0; + } + + if (index == this.lastRequestedIndex) { + this.rowFromServer.setPosition(this.lastRequestedPos); + + return this.lastRequestedPos; + } + + int startingIndex = 0; + + if (index > this.lastRequestedIndex) { + if (this.lastRequestedIndex >= 0) { + startingIndex = this.lastRequestedIndex; + } else { + // First-time "scan" + startingIndex = 0; + this.lastRequestedPos = this.homePosition; + } + + this.rowFromServer.setPosition(this.lastRequestedPos); + } else { + this.rowFromServer.setPosition(this.homePosition); + } + + for (int i = startingIndex; i < index; i++) { + if (this.isNull[i]) { + continue; + } + + int curPosition = this.rowFromServer.getPosition(); + + switch (this.metadata[i].getMysqlType()) { + case MysqlDefs.FIELD_TYPE_NULL: + break; // for dummy binds + + case MysqlDefs.FIELD_TYPE_TINY: + + this.rowFromServer.setPosition(curPosition + 1); + break; + + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + this.rowFromServer.setPosition(curPosition + 2); + + break; + case MysqlDefs.FIELD_TYPE_LONG: + case MysqlDefs.FIELD_TYPE_INT24: + this.rowFromServer.setPosition(curPosition + 4); + + break; + case MysqlDefs.FIELD_TYPE_LONGLONG: + this.rowFromServer.setPosition(curPosition + 8); + + break; + case MysqlDefs.FIELD_TYPE_FLOAT: + this.rowFromServer.setPosition(curPosition + 4); + + break; + case MysqlDefs.FIELD_TYPE_DOUBLE: + this.rowFromServer.setPosition(curPosition + 8); + + break; + case MysqlDefs.FIELD_TYPE_TIME: + this.rowFromServer.fastSkipLenByteArray(); + + break; + case MysqlDefs.FIELD_TYPE_DATE: + + this.rowFromServer.fastSkipLenByteArray(); + + break; + case MysqlDefs.FIELD_TYPE_DATETIME: + case MysqlDefs.FIELD_TYPE_TIMESTAMP: + this.rowFromServer.fastSkipLenByteArray(); + + break; + case MysqlDefs.FIELD_TYPE_TINY_BLOB: + case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: + case MysqlDefs.FIELD_TYPE_LONG_BLOB: + case MysqlDefs.FIELD_TYPE_BLOB: + case MysqlDefs.FIELD_TYPE_VAR_STRING: + case MysqlDefs.FIELD_TYPE_VARCHAR: + case MysqlDefs.FIELD_TYPE_STRING: + case MysqlDefs.FIELD_TYPE_DECIMAL: + case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: + case MysqlDefs.FIELD_TYPE_GEOMETRY: + case MysqlDefs.FIELD_TYPE_BIT: + this.rowFromServer.fastSkipLenByteArray(); + + break; + + default: + throw SQLError.createSQLException(Messages + .getString("MysqlIO.97") //$NON-NLS-1$ + + this.metadata[i].getMysqlType() + + Messages.getString("MysqlIO.98") + + (i + 1) + + Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$ + + this.metadata.length + + Messages.getString("MysqlIO.100"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } + + this.lastRequestedIndex = index; + this.lastRequestedPos = this.rowFromServer.getPosition(); + + return this.lastRequestedPos; + } + + public synchronized InputStream getBinaryInputStream(int columnIndex) + throws SQLException { + if (this.isBinaryEncoded) { + if (isNull(columnIndex)) { + return null; + } + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + if (length == Buffer.NULL_LENGTH) { + return null; + } + + InputStream stream = new ByteArrayInputStream(this.rowFromServer + .getByteBuffer(), offset, (int) length); + + if (this.openStreams == null) { + this.openStreams = new LinkedList(); + } + + return stream; + } + + public byte[] getColumnValue(int index) throws SQLException { + findAndSeekToOffset(index); + + if (!this.isBinaryEncoded) { + return this.rowFromServer.readLenByteArray(0); + } + + if (this.isNull[index]) { + return null; + } + + switch (this.metadata[index].getMysqlType()) { + case MysqlDefs.FIELD_TYPE_NULL: + return null; + + case MysqlDefs.FIELD_TYPE_TINY: + return new byte[] { this.rowFromServer.readByte() }; + + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + return this.rowFromServer.getBytes(2); + + case MysqlDefs.FIELD_TYPE_LONG: + case MysqlDefs.FIELD_TYPE_INT24: + return this.rowFromServer.getBytes(4); + + case MysqlDefs.FIELD_TYPE_LONGLONG: + return this.rowFromServer.getBytes(8); + + case MysqlDefs.FIELD_TYPE_FLOAT: + return this.rowFromServer.getBytes(4); + + case MysqlDefs.FIELD_TYPE_DOUBLE: + return this.rowFromServer.getBytes(8); + + case MysqlDefs.FIELD_TYPE_TIME: + case MysqlDefs.FIELD_TYPE_DATE: + case MysqlDefs.FIELD_TYPE_DATETIME: + case MysqlDefs.FIELD_TYPE_TIMESTAMP: + case MysqlDefs.FIELD_TYPE_TINY_BLOB: + case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: + case MysqlDefs.FIELD_TYPE_LONG_BLOB: + case MysqlDefs.FIELD_TYPE_BLOB: + case MysqlDefs.FIELD_TYPE_VAR_STRING: + case MysqlDefs.FIELD_TYPE_VARCHAR: + case MysqlDefs.FIELD_TYPE_STRING: + case MysqlDefs.FIELD_TYPE_DECIMAL: + case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: + case MysqlDefs.FIELD_TYPE_GEOMETRY: + case MysqlDefs.FIELD_TYPE_BIT: + return this.rowFromServer.readLenByteArray(0); + + default: + throw SQLError.createSQLException(Messages.getString("MysqlIO.97") //$NON-NLS-1$ + + this.metadata[index].getMysqlType() + + Messages.getString("MysqlIO.98") + + (index + 1) + + Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$ + + this.metadata.length + Messages.getString("MysqlIO.100"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } + + public int getInt(int columnIndex) throws SQLException { + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + if (length == Buffer.NULL_LENGTH) { + return 0; + } + + return StringUtils.getInt(this.rowFromServer.getByteBuffer(), offset, + offset + (int) length); + } + + public long getLong(int columnIndex) throws SQLException { + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + if (length == Buffer.NULL_LENGTH) { + return 0; + } + + return StringUtils.getLong(this.rowFromServer.getByteBuffer(), offset, + offset + (int) length); + } + + public double getNativeDouble(int columnIndex) throws SQLException { + if (isNull(columnIndex)) { + return 0; + } + + findAndSeekToOffset(columnIndex); + + int offset = this.rowFromServer.getPosition(); + + return getNativeDouble(this.rowFromServer.getByteBuffer(), offset); + } + + public float getNativeFloat(int columnIndex) throws SQLException { + if (isNull(columnIndex)) { + return 0; + } + + findAndSeekToOffset(columnIndex); + + int offset = this.rowFromServer.getPosition(); + + return getNativeFloat(this.rowFromServer.getByteBuffer(), offset); + } + + public int getNativeInt(int columnIndex) throws SQLException { + if (isNull(columnIndex)) { + return 0; + } + + findAndSeekToOffset(columnIndex); + + int offset = this.rowFromServer.getPosition(); + + return getNativeInt(this.rowFromServer.getByteBuffer(), offset); + } + + public long getNativeLong(int columnIndex) throws SQLException { + if (isNull(columnIndex)) { + return 0; + } + + findAndSeekToOffset(columnIndex); + + int offset = this.rowFromServer.getPosition(); + + return getNativeLong(this.rowFromServer.getByteBuffer(), offset); + } + + public short getNativeShort(int columnIndex) throws SQLException { + if (isNull(columnIndex)) { + return 0; + } + + findAndSeekToOffset(columnIndex); + + int offset = this.rowFromServer.getPosition(); + + return getNativeShort(this.rowFromServer.getByteBuffer(), offset); + } + + public Timestamp getNativeTimestamp(int columnIndex, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getNativeTimestamp(this.rowFromServer.getByteBuffer(), offset, + (int) length, targetCalendar, tz, rollForward, conn, rs); + } + + public Reader getReader(int columnIndex) throws SQLException { + InputStream stream = getBinaryInputStream(columnIndex); + + if (stream == null) { + return null; + } + + try { + return new InputStreamReader(stream, this.metadata[columnIndex] + .getCharacterSet()); + } catch (UnsupportedEncodingException e) { + SQLException sqlEx = SQLError.createSQLException("", this.exceptionInterceptor); + + sqlEx.initCause(e); + + throw sqlEx; + } + } + + public String getString(int columnIndex, String encoding, MySQLConnection conn) + throws SQLException { + if (this.isBinaryEncoded) { + if (isNull(columnIndex)) { + return null; + } + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + if (length == Buffer.NULL_LENGTH) { + return null; + } + + if (length == 0) { + return ""; + } + + // TODO: I don't like this, would like to push functionality back + // to the buffer class somehow + + int offset = this.rowFromServer.getPosition(); + + return getString(encoding, conn, this.rowFromServer.getByteBuffer(), + offset, (int) length); + } + + public Time getTimeFast(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getTimeFast(columnIndex, this.rowFromServer.getByteBuffer(), + offset, (int)length, targetCalendar, tz, rollForward, conn, rs); + } + + public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getTimestampFast(columnIndex, + this.rowFromServer.getByteBuffer(), offset, (int)length, targetCalendar, tz, + rollForward, conn, rs); + } + + public boolean isFloatingPointNumber(int index) throws SQLException { + if (this.isBinaryEncoded) { + switch (this.metadata[index].getSQLType()) { + case Types.FLOAT: + case Types.DOUBLE: + case Types.DECIMAL: + case Types.NUMERIC: + return true; + default: + return false; + } + } + + findAndSeekToOffset(index); + + long length = this.rowFromServer.readFieldLength(); + + if (length == Buffer.NULL_LENGTH) { + return false; + } + + if (length == 0) { + return false; + } + + int offset = this.rowFromServer.getPosition(); + byte[] buffer = this.rowFromServer.getByteBuffer(); + + for (int i = 0; i < (int) length; i++) { + char c = (char) buffer[offset + i]; + + if ((c == 'e') || (c == 'E')) { + return true; + } + } + + return false; + } + + public boolean isNull(int index) throws SQLException { + if (!this.isBinaryEncoded) { + findAndSeekToOffset(index); + + return this.rowFromServer.readFieldLength() == Buffer.NULL_LENGTH; + } + + return this.isNull[index]; + } + + public long length(int index) throws SQLException { + findAndSeekToOffset(index); + + long length = this.rowFromServer.readFieldLength(); + + if (length == Buffer.NULL_LENGTH) { + return 0; + } + + return length; + } + + public void setColumnValue(int index, byte[] value) throws SQLException { + throw new OperationNotSupportedException(); + } + + public ResultSetRow setMetadata(Field[] f) throws SQLException { + super.setMetadata(f); + + if (this.isBinaryEncoded) { + setupIsNullBitmask(); + } + + return this; + } + + /** + * Unpacks the bitmask at the head of the row packet that tells us what + * columns hold null values, and sets the "home" position directly after the + * bitmask. + */ + private void setupIsNullBitmask() throws SQLException { + if (this.isNull != null) { + return; // we've already done this + } + + this.rowFromServer.setPosition(this.preNullBitmaskHomePosition); + + int nullCount = (this.metadata.length + 9) / 8; + + byte[] nullBitMask = new byte[nullCount]; + + for (int i = 0; i < nullCount; i++) { + nullBitMask[i] = this.rowFromServer.readByte(); + } + + this.homePosition = this.rowFromServer.getPosition(); + + this.isNull = new boolean[this.metadata.length]; + + int nullMaskPos = 0; + int bit = 4; // first two bits are reserved for future use + + for (int i = 0; i < this.metadata.length; i++) { + + this.isNull[i] = ((nullBitMask[nullMaskPos] & bit) != 0); + + if (((bit <<= 1) & 255) == 0) { + bit = 1; /* To next byte */ + + nullMaskPos++; + } + } + } + + public Date getDateFast(int columnIndex, MySQLConnection conn, + ResultSetImpl rs, Calendar targetCalendar) throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getDateFast(columnIndex, this.rowFromServer.getByteBuffer(), + offset, (int)length, conn, rs, targetCalendar); + } + + public java.sql.Date getNativeDate(int columnIndex, MySQLConnection conn, + ResultSetImpl rs, Calendar cal) throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getNativeDate(columnIndex, this.rowFromServer.getByteBuffer(), + offset, (int) length, conn, rs, cal); + } + + public Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar, + int jdbcType, int mysqlType, TimeZone tz, + boolean rollForward, MySQLConnection conn, ResultSetImpl rs) + throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getNativeDateTimeValue(columnIndex, this.rowFromServer + .getByteBuffer(), offset, (int) length, targetCalendar, jdbcType, + mysqlType, tz, rollForward, conn, rs); + } + + public Time getNativeTime(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + if (isNull(columnIndex)) { + return null; + } + + findAndSeekToOffset(columnIndex); + + long length = this.rowFromServer.readFieldLength(); + + int offset = this.rowFromServer.getPosition(); + + return getNativeTime(columnIndex, this.rowFromServer.getByteBuffer(), + offset, (int) length, targetCalendar, tz, rollForward, conn, rs); + } + + public int getBytesSize() { + return this.rowFromServer.getBufLength(); + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ByteArrayRow.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ByteArrayRow.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ByteArrayRow.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,297 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.sql.Date; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.TimeZone; + +/** + * A RowHolder implementation that is for cached results (a-la + * mysql_store_result()). + * + * @version $Id$ + */ +public class ByteArrayRow extends ResultSetRow { + + byte[][] internalRowData; + + public ByteArrayRow(byte[][] internalRowData, ExceptionInterceptor exceptionInterceptor) { + super(exceptionInterceptor); + + this.internalRowData = internalRowData; + } + + public byte[] getColumnValue(int index) throws SQLException { + return this.internalRowData[index]; + } + + public void setColumnValue(int index, byte[] value) throws SQLException { + this.internalRowData[index] = value; + } + + public String getString(int index, String encoding, MySQLConnection conn) + throws SQLException { + byte[] columnData = this.internalRowData[index]; + + if (columnData == null) { + return null; + } + + return getString(encoding, conn, columnData, 0, columnData.length); + } + + public boolean isNull(int index) throws SQLException { + return this.internalRowData[index] == null; + } + + public boolean isFloatingPointNumber(int index) throws SQLException { + byte[] numAsBytes = this.internalRowData[index]; + + if (this.internalRowData[index] == null + || this.internalRowData[index].length == 0) { + return false; + } + + for (int i = 0; i < numAsBytes.length; i++) { + if (((char) numAsBytes[i] == 'e') || ((char) numAsBytes[i] == 'E')) { + return true; + } + } + + return false; + } + + public long length(int index) throws SQLException { + if (this.internalRowData[index] == null) { + return 0; + } + + return this.internalRowData[index].length; + } + + public int getInt(int columnIndex) { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return StringUtils.getInt(this.internalRowData[columnIndex]); + } + + public long getLong(int columnIndex) { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return StringUtils.getLong(this.internalRowData[columnIndex]); + } + + public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + byte[] columnValue = this.internalRowData[columnIndex]; + + if (columnValue == null) { + return null; + } + + return getTimestampFast(columnIndex, this.internalRowData[columnIndex], + 0, columnValue.length, targetCalendar, tz, rollForward, conn, + rs); + } + + public double getNativeDouble(int columnIndex) throws SQLException { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return getNativeDouble(this.internalRowData[columnIndex], 0); + } + + public float getNativeFloat(int columnIndex) throws SQLException { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return getNativeFloat(this.internalRowData[columnIndex], 0); + } + + public int getNativeInt(int columnIndex) throws SQLException { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return getNativeInt(this.internalRowData[columnIndex], 0); + } + + public long getNativeLong(int columnIndex) throws SQLException { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return getNativeLong(this.internalRowData[columnIndex], 0); + } + + public short getNativeShort(int columnIndex) throws SQLException { + if (this.internalRowData[columnIndex] == null) { + return 0; + } + + return getNativeShort(this.internalRowData[columnIndex], 0); + } + + public Timestamp getNativeTimestamp(int columnIndex, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException { + byte[] bits = this.internalRowData[columnIndex]; + + if (bits == null) { + return null; + } + + return getNativeTimestamp(bits, 0, bits.length, targetCalendar, tz, + rollForward, conn, rs); + } + + public void closeOpenStreams() { + // no-op for this type + } + + public InputStream getBinaryInputStream(int columnIndex) + throws SQLException { + if (this.internalRowData[columnIndex] == null) { + return null; + } + + return new ByteArrayInputStream(this.internalRowData[columnIndex]); + } + + public Reader getReader(int columnIndex) throws SQLException { + InputStream stream = getBinaryInputStream(columnIndex); + + if (stream == null) { + return null; + } + + try { + return new InputStreamReader(stream, this.metadata[columnIndex] + .getCharacterSet()); + } catch (UnsupportedEncodingException e) { + SQLException sqlEx = SQLError.createSQLException("", this.exceptionInterceptor); + + sqlEx.initCause(e); + + throw sqlEx; + } + } + + public Time getTimeFast(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + byte[] columnValue = this.internalRowData[columnIndex]; + + if (columnValue == null) { + return null; + } + + return getTimeFast(columnIndex, this.internalRowData[columnIndex], 0, + columnValue.length, targetCalendar, tz, rollForward, conn, rs); + } + + public Date getDateFast(int columnIndex, MySQLConnection conn, + ResultSetImpl rs, Calendar targetCalendar) throws SQLException { + byte[] columnValue = this.internalRowData[columnIndex]; + + if (columnValue == null) { + return null; + } + + return getDateFast(columnIndex, this.internalRowData[columnIndex], 0, + columnValue.length, conn, rs, targetCalendar); + } + + public Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar, + int jdbcType, int mysqlType, TimeZone tz, + boolean rollForward, MySQLConnection conn, ResultSetImpl rs) + throws SQLException { + byte[] columnValue = this.internalRowData[columnIndex]; + + if (columnValue == null) { + return null; + } + + return getNativeDateTimeValue(columnIndex, columnValue, 0, + columnValue.length, targetCalendar, jdbcType, mysqlType, tz, + rollForward, conn, rs); + } + + public Date getNativeDate(int columnIndex, MySQLConnection conn, + ResultSetImpl rs, Calendar cal) throws SQLException { + byte[] columnValue = this.internalRowData[columnIndex]; + + if (columnValue == null) { + return null; + } + + return getNativeDate(columnIndex, columnValue, 0, columnValue.length, + conn, rs, cal); + } + + public Time getNativeTime(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + byte[] columnValue = this.internalRowData[columnIndex]; + + if (columnValue == null) { + return null; + } + + return getNativeTime(columnIndex, columnValue, 0, columnValue.length, + targetCalendar, tz, rollForward, conn, rs); + } + + public int getBytesSize() { + if (internalRowData == null) { + return 0; + } + + int bytesSize = 0; + + for (int i = 0; i < internalRowData.length; i++) { + if (internalRowData[i] != null) { + bytesSize += internalRowData[i].length; + } + } + + return bytesSize; + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CacheAdapter.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CacheAdapter.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CacheAdapter.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,40 @@ +/* + Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.util.Set; + + + +public interface CacheAdapter { + V get(K key); + + void put(K key, V value); + + void invalidate(K key); + + void invalidateAll(Set keys); + + void invalidateAll(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CacheAdapterFactory.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CacheAdapterFactory.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CacheAdapterFactory.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,35 @@ +/* + Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +public interface CacheAdapterFactory { + + public abstract CacheAdapter getInstance(Connection forConn, String url, + int cacheMaxSize, int maxKeySize, Properties connectionProperties) + throws SQLException; + +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CachedResultSetMetaData.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CachedResultSetMetaData.java (.../CachedResultSetMetaData.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CachedResultSetMetaData.java (.../CachedResultSetMetaData.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,40 +1,56 @@ /* - Copyright (C) 2007 MySQL AB + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ package com.mysql.jdbc; import java.util.Map; -class CachedResultSetMetaData { +public class CachedResultSetMetaData { /** Map column names (and all of their permutations) to column indices */ - Map columnNameToIndex = null; + Map columnNameToIndex = null; /** Cached Field info */ Field[] fields; /** Map of fully-specified column names to column indices */ - Map fullColumnNameToIndex = null; + Map fullColumnNameToIndex = null; /** Cached ResultSetMetaData */ java.sql.ResultSetMetaData metadata; + + public Map getColumnNameToIndex() { + return columnNameToIndex; + } + + public Field[] getFields() { + return fields; + } + + public Map getFullColumnNameToIndex() { + return fullColumnNameToIndex; + } + + public java.sql.ResultSetMetaData getMetadata() { + return metadata; + } } \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CallableStatement.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CallableStatement.java (.../CallableStatement.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CallableStatement.java (.../CallableStatement.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,52 +1,50 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ + package com.mysql.jdbc; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; - +import java.lang.reflect.Constructor; import java.math.BigDecimal; - import java.net.URL; - import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.ParameterMetaData; import java.sql.Ref; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; - import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; /** @@ -58,7 +56,38 @@ */ public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement { - class CallableStatementParam { + protected final static Constructor JDBC_4_CSTMT_2_ARGS_CTOR; + + protected final static Constructor JDBC_4_CSTMT_4_ARGS_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_CSTMT_2_ARGS_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4CallableStatement") + .getConstructor( + new Class[] { MySQLConnection.class, + CallableStatementParamInfo.class }); + JDBC_4_CSTMT_4_ARGS_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4CallableStatement") + .getConstructor( + new Class[] { MySQLConnection.class, + String.class, String.class, + Boolean.TYPE }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_CSTMT_4_ARGS_CTOR = null; + JDBC_4_CSTMT_2_ARGS_CTOR = null; + } + } + + protected static class CallableStatementParam { int desiredJdbcType; int index; @@ -107,7 +136,7 @@ } } - class CallableStatementParamInfo { + protected class CallableStatementParamInfo { String catalogInUse; boolean isFunctionCall; @@ -116,11 +145,22 @@ int numParameters; - List parameterList; + List parameterList; - Map parameterMap; + Map parameterMap; + /** + * synchronized externally in checkReadOnlyProcedure() + */ + boolean isReadOnlySafeProcedure = false; + + /** + * synchronized externally in checkReadOnlyProcedure() + */ + boolean isReadOnlySafeChecked = false; + + /** * Constructor that converts a full list of parameter metadata into one * that only represents the placeholders present in the {CALL ()}. * @@ -131,11 +171,14 @@ this.nativeSql = originalSql; this.catalogInUse = currentCatalog; isFunctionCall = fullParamInfo.isFunctionCall; + @SuppressWarnings("synthetic-access") int[] localParameterMap = placeholderToParameterIndexMap; int parameterMapLength = localParameterMap.length; - parameterList = new ArrayList(fullParamInfo.numParameters); - parameterMap = new HashMap(fullParamInfo.numParameters); + this.isReadOnlySafeProcedure = fullParamInfo.isReadOnlySafeProcedure; + this.isReadOnlySafeChecked = fullParamInfo.isReadOnlySafeChecked; + parameterList = new ArrayList(fullParamInfo.numParameters); + parameterMap = new HashMap(fullParamInfo.numParameters); if (isFunctionCall) { // Take the return value @@ -146,7 +189,7 @@ for (int i = 0; i < parameterMapLength; i++) { if (localParameterMap[i] != 0) { - CallableStatementParam param = (CallableStatementParam)fullParamInfo.parameterList.get(localParameterMap[i] + offset); + CallableStatementParam param = fullParamInfo.parameterList.get(localParameterMap[i] + offset); parameterList.add(param); parameterMap.put(param.paramName, param); @@ -156,6 +199,7 @@ this.numParameters = parameterList.size(); } + @SuppressWarnings("synthetic-access") CallableStatementParamInfo(java.sql.ResultSet paramTypesRs) throws SQLException { boolean hadRows = paramTypesRs.last(); @@ -167,8 +211,8 @@ if (hadRows) { this.numParameters = paramTypesRs.getRow(); - this.parameterList = new ArrayList(this.numParameters); - this.parameterMap = new HashMap(this.numParameters); + this.parameterList = new ArrayList(this.numParameters); + this.parameterMap = new HashMap(this.numParameters); paramTypesRs.beforeFirst(); @@ -179,8 +223,8 @@ if (isFunctionCall) { this.numParameters += 1; - } } + } private void addParametersFromDBMD(java.sql.ResultSet paramTypesRs) throws SQLException { @@ -230,7 +274,7 @@ throw SQLError.createSQLException( Messages.getString("CallableStatement.11") + paramIndex //$NON-NLS-1$ + Messages.getString("CallableStatement.12") + numParameters //$NON-NLS-1$ - + Messages.getString("CallableStatement.13"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + + Messages.getString("CallableStatement.13"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ } } @@ -240,16 +284,15 @@ * @see java.lang.Object#clone() */ protected Object clone() throws CloneNotSupportedException { - // TODO Auto-generated method stub return super.clone(); } CallableStatementParam getParameter(int index) { - return (CallableStatementParam) this.parameterList.get(index); + return this.parameterList.get(index); } CallableStatementParam getParameter(String name) { - return (CallableStatementParam) this.parameterMap.get(name); + return this.parameterMap.get(name); } public String getParameterClassName(int arg0) throws SQLException { @@ -266,15 +309,15 @@ mysqlTypeIfKnown = MysqlDefs.FIELD_TYPE_INT24; } - return ResultSetMetaData.getClassNameForJavaType(getParameterType(arg0), - isUnsigned, mysqlTypeIfKnown, isBinaryOrBlob, false); + return ResultSetMetaData.getClassNameForJavaType(getParameterType(arg0), isUnsigned, mysqlTypeIfKnown, + isBinaryOrBlob, false, connection.getYearIsDateType()); } public int getParameterCount() throws SQLException { if (this.parameterList == null) { return 0; } - + return this.parameterList.size(); } @@ -320,7 +363,7 @@ return false; } - Iterator iterator() { + Iterator iterator() { return this.parameterList.iterator(); } @@ -335,7 +378,7 @@ * quite a bit out there in the wild (Websphere, FreeBSD, anyone?) */ - class CallableStatementParamInfoJDBC3 extends CallableStatementParamInfo + protected class CallableStatementParamInfoJDBC3 extends CallableStatementParamInfo implements ParameterMetaData { CallableStatementParamInfoJDBC3(java.sql.ResultSet paramTypesRs) @@ -346,13 +389,62 @@ public CallableStatementParamInfoJDBC3(CallableStatementParamInfo paramInfo) { super(paramInfo); } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public Object unwrap(Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return Util.cast(iface, this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } } private final static int NOT_OUTPUT_PARAMETER_INDICATOR = Integer.MIN_VALUE; private final static String PARAMETER_NAMESPACE_PREFIX = "@com_mysql_jdbc_outparam_"; //$NON-NLS-1$ private static String mangleParameterName(String origParameterName) { + //Fixed for 5.5+ in callers if (origParameterName == null) { return null; } @@ -375,22 +467,22 @@ private boolean callingStoredFunction = false; - private ResultSet functionReturnValueResults; + private ResultSetInternalMethods functionReturnValueResults; private boolean hasOutputParams = false; // private List parameterList; // private Map parameterMap; - private ResultSet outputParameterResults; + private ResultSetInternalMethods outputParameterResults; - private boolean outputParamWasNull = false; + protected boolean outputParamWasNull = false; private int[] parameterIndexToRsIndex; protected CallableStatementParamInfo paramInfo; private CallableStatementParam returnValueParam; - + /** * Creates a new CallableStatement * @@ -402,7 +494,7 @@ * @throws SQLException * if an error occurs */ - public CallableStatement(Connection conn, + public CallableStatement(MySQLConnection conn, CallableStatementParamInfo paramInfo) throws SQLException { super(conn, paramInfo.nativeSql, paramInfo.catalogInUse); @@ -412,85 +504,105 @@ if (this.callingStoredFunction) { this.parameterCount += 1; } + + this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec } /** - * Creates a new CallableStatement - * - * @param conn - * the connection creating this statement - * @param catalog - * catalog the current catalog - * - * @throws SQLException - * if an error occurs + * Creates a callable statement instance -- We need to provide factory-style methods + * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise + * the class verifier complains when it tries to load JDBC4-only interface + * classes that are present in JDBC4 method signatures. */ - public CallableStatement(Connection conn, String catalog) - throws SQLException { - super(conn, catalog, null); - determineParameterTypes(); - generateParameterMap(); - - if (this.callingStoredFunction) { - this.parameterCount += 1; + protected static CallableStatement getInstance(MySQLConnection conn, String sql, + String catalog, boolean isFunctionCall) throws SQLException { + if (!Util.isJdbc4()) { + return new CallableStatement(conn, sql, catalog, isFunctionCall); } + + return (CallableStatement) Util.handleNewInstance( + JDBC_4_CSTMT_4_ARGS_CTOR, new Object[] { conn, sql, catalog, + Boolean.valueOf(isFunctionCall) }, conn.getExceptionInterceptor()); } + + /** + * Creates a callable statement instance -- We need to provide factory-style methods + * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise + * the class verifier complains when it tries to load JDBC4-only interface + * classes that are present in JDBC4 method signatures. + */ + protected static CallableStatement getInstance(MySQLConnection conn, + CallableStatementParamInfo paramInfo) throws SQLException { + if (!Util.isJdbc4()) { + return new CallableStatement(conn, paramInfo); + } + + return (CallableStatement) Util.handleNewInstance( + JDBC_4_CSTMT_2_ARGS_CTOR, new Object[] { conn, paramInfo }, conn.getExceptionInterceptor()); + + } + private int[] placeholderToParameterIndexMap; - private void generateParameterMap() throws SQLException { - // if the user specified some parameters as literals, we need to - // provide a map from the specified placeholders to the actual - // parameter numbers - - int parameterCountFromMetaData = this.paramInfo.getParameterCount(); - - // Ignore the first ? if this is a stored function, it doesn't count - - if (this.callingStoredFunction) { - parameterCountFromMetaData--; - } - - if (this.paramInfo != null && - this.parameterCount != parameterCountFromMetaData) { - this.placeholderToParameterIndexMap = new int[this.parameterCount]; + synchronized (checkClosed().getConnectionMutex()) { + if (this.paramInfo == null) { + return; + } - int startPos = this.callingStoredFunction ? StringUtils.indexOfIgnoreCase(this.originalSql, - "SELECT") : StringUtils.indexOfIgnoreCase(this.originalSql, "CALL"); + // if the user specified some parameters as literals, we need to + // provide a map from the specified placeholders to the actual + // parameter numbers - if (startPos != -1) { - int parenOpenPos = this.originalSql.indexOf('(', startPos + 4); + int parameterCountFromMetaData = this.paramInfo.getParameterCount(); + + // Ignore the first ? if this is a stored function, it doesn't count + + if (this.callingStoredFunction) { + parameterCountFromMetaData--; + } + + if (this.paramInfo != null && + this.parameterCount != parameterCountFromMetaData) { + this.placeholderToParameterIndexMap = new int[this.parameterCount]; - if (parenOpenPos != -1) { - int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, - this.originalSql, ")", '\'', true); + int startPos = this.callingStoredFunction ? StringUtils.indexOfIgnoreCase(this.originalSql, + "SELECT") : StringUtils.indexOfIgnoreCase(this.originalSql, "CALL"); + + if (startPos != -1) { + int parenOpenPos = this.originalSql.indexOf('(', startPos + 4); - if (parenClosePos != -1) { - List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true); + if (parenOpenPos != -1) { + int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, + this.originalSql, ")", '\'', true); - int numParsedParameters = parsedParameters.size(); - - // sanity check - - if (numParsedParameters != this.parameterCount) { - // bail? - } - - int placeholderCount = 0; - - for (int i = 0; i < numParsedParameters; i++) { - if (((String)parsedParameters.get(i)).equals("?")) { - this.placeholderToParameterIndexMap[placeholderCount++] = i; + if (parenClosePos != -1) { + List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true); + + int numParsedParameters = parsedParameters.size(); + + // sanity check + + if (numParsedParameters != this.parameterCount) { + // bail? } + + int placeholderCount = 0; + + for (int i = 0; i < numParsedParameters; i++) { + if (((String)parsedParameters.get(i)).equals("?")) { + this.placeholderToParameterIndexMap[placeholderCount++] = i; + } + } } } } } } } - + /** * Creates a new CallableStatement * @@ -504,18 +616,29 @@ * @throws SQLException * if an error occurs */ - public CallableStatement(Connection conn, String sql, String catalog, + public CallableStatement(MySQLConnection conn, String sql, String catalog, boolean isFunctionCall) throws SQLException { super(conn, sql, catalog); this.callingStoredFunction = isFunctionCall; - determineParameterTypes(); - generateParameterMap(); - - if (this.callingStoredFunction) { + if (!this.callingStoredFunction) { + if (!StringUtils.startsWithIgnoreCaseAndWs(sql, "CALL")) { + // not really a stored procedure call + fakeParameterTypes(false); + } else { + determineParameterTypes(); + } + + generateParameterMap(); + } else { + determineParameterTypes(); + generateParameterMap(); + this.parameterCount += 1; } + + this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec } /* @@ -532,51 +655,53 @@ private CallableStatementParam checkIsOutputParam(int paramIndex) throws SQLException { - if (this.callingStoredFunction) { - if (paramIndex == 1) { - - if (this.returnValueParam == null) { - this.returnValueParam = new CallableStatementParam("", 0, - false, true, Types.VARCHAR, "VARCHAR", 0, 0, - DatabaseMetaData.attributeNullableUnknown, - DatabaseMetaData.procedureColumnReturn); + synchronized (checkClosed().getConnectionMutex()) { + if (this.callingStoredFunction) { + if (paramIndex == 1) { + + if (this.returnValueParam == null) { + this.returnValueParam = new CallableStatementParam("", 0, + false, true, Types.VARCHAR, "VARCHAR", 0, 0, + DatabaseMetaData.attributeNullableUnknown, + DatabaseMetaData.procedureColumnReturn); + } + + return this.returnValueParam; } - - return this.returnValueParam; + + // Move to position in output result set + paramIndex--; } - - // Move to position in output result set - paramIndex--; + + checkParameterIndexBounds(paramIndex); + + int localParamIndex = paramIndex - 1; + + if (this.placeholderToParameterIndexMap != null) { + localParamIndex = this.placeholderToParameterIndexMap[localParamIndex]; + } + + CallableStatementParam paramDescriptor = this.paramInfo + .getParameter(localParamIndex); + + // We don't have reliable metadata in this case, trust + // the caller + + if (this.connection.getNoAccessToProcedureBodies()) { + paramDescriptor.isOut = true; + paramDescriptor.isIn = true; + paramDescriptor.inOutModifier = DatabaseMetaData.procedureColumnInOut; + } else if (!paramDescriptor.isOut) { + throw SQLError.createSQLException( + Messages.getString("CallableStatement.9") + paramIndex //$NON-NLS-1$ + + Messages.getString("CallableStatement.10"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + this.hasOutputParams = true; + + return paramDescriptor; } - - checkParameterIndexBounds(paramIndex); - - int localParamIndex = paramIndex - 1; - - if (this.placeholderToParameterIndexMap != null) { - localParamIndex = this.placeholderToParameterIndexMap[localParamIndex]; - } - - CallableStatementParam paramDescriptor = this.paramInfo - .getParameter(localParamIndex); - - // We don't have reliable metadata in this case, trust - // the caller - - if (this.connection.getNoAccessToProcedureBodies()) { - paramDescriptor.isOut = true; - paramDescriptor.isIn = true; - paramDescriptor.inOutModifier = DatabaseMetaData.procedureColumnInOut; - } else if (!paramDescriptor.isOut) { - throw SQLError.createSQLException( - Messages.getString("CallableStatement.9") + paramIndex //$NON-NLS-1$ - + Messages.getString("CallableStatement.10"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - this.hasOutputParams = true; - - return paramDescriptor; } /** @@ -587,7 +712,9 @@ * @throws SQLException */ private void checkParameterIndexBounds(int paramIndex) throws SQLException { - this.paramInfo.checkBounds(paramIndex); + synchronized (checkClosed().getConnectionMutex()) { + this.paramInfo.checkBounds(paramIndex); + } } /** @@ -601,19 +728,21 @@ private void checkStreamability() throws SQLException { if (this.hasOutputParams && createStreamingResultSet()) { throw SQLError.createSQLException(Messages.getString("CallableStatement.14"), //$NON-NLS-1$ - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); } } - public synchronized void clearParameters() throws SQLException { - super.clearParameters(); - - try { - if (this.outputParameterResults != null) { - this.outputParameterResults.close(); + public void clearParameters() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + super.clearParameters(); + + try { + if (this.outputParameterResults != null) { + this.outputParameterResults.close(); + } + } finally { + this.outputParameterResults = null; } - } finally { - this.outputParameterResults = null; } } @@ -623,120 +752,155 @@ * * @throws SQLException if we can't build the metadata. */ - private void fakeParameterTypes() throws SQLException { - Field[] fields = new Field[13]; - - fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0); - fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0); - fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 0); - fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 0); - fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 0); - fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 0); - fields[7] = new Field("", "PRECISION", Types.INTEGER, 0); - fields[8] = new Field("", "LENGTH", Types.INTEGER, 0); - fields[9] = new Field("", "SCALE", Types.SMALLINT, 0); - fields[10] = new Field("", "RADIX", Types.SMALLINT, 0); - fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 0); - fields[12] = new Field("", "REMARKS", Types.CHAR, 0); - - String procName = extractProcedureName(); - - byte[] procNameAsBytes = null; - - try { - procNameAsBytes = procName.getBytes("UTF-8"); - } catch (UnsupportedEncodingException ueEx) { - procNameAsBytes = StringUtils.s2b(procName, this.connection); + private void fakeParameterTypes(boolean isReallyProcedure) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + Field[] fields = new Field[13]; + + fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0); + fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0); + fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0); + fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 0); + fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 0); + fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 0); + fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 0); + fields[7] = new Field("", "PRECISION", Types.INTEGER, 0); + fields[8] = new Field("", "LENGTH", Types.INTEGER, 0); + fields[9] = new Field("", "SCALE", Types.SMALLINT, 0); + fields[10] = new Field("", "RADIX", Types.SMALLINT, 0); + fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 0); + fields[12] = new Field("", "REMARKS", Types.CHAR, 0); + + String procName = isReallyProcedure ? extractProcedureName() : null; + + byte[] procNameAsBytes = null; + + try { + procNameAsBytes = procName == null ? null : StringUtils.getBytes(procName, "UTF-8"); + } catch (UnsupportedEncodingException ueEx) { + procNameAsBytes = StringUtils.s2b(procName, this.connection); + } + + ArrayList resultRows = new ArrayList(); + + for (int i = 0; i < this.parameterCount; i++) { + byte[][] row = new byte[13][]; + row[0] = null; // PROCEDURE_CAT + row[1] = null; // PROCEDURE_SCHEM + row[2] = procNameAsBytes; // PROCEDURE/NAME + row[3] = StringUtils.s2b(String.valueOf(i), this.connection); // COLUMN_NAME + + row[4] = StringUtils.s2b(String + .valueOf(DatabaseMetaData.procedureColumnIn), + this.connection); + + row[5] = StringUtils.s2b(String.valueOf(Types.VARCHAR), + this.connection); // DATA_TYPE + row[6] = StringUtils.s2b("VARCHAR", this.connection); // TYPE_NAME + row[7] = StringUtils.s2b(Integer.toString(65535), this.connection); // PRECISION + row[8] = StringUtils.s2b(Integer.toString(65535), this.connection); // LENGTH + row[9] = StringUtils.s2b(Integer.toString(0), this.connection); // SCALE + row[10] = StringUtils.s2b(Integer.toString(10), this.connection); // RADIX + + row[11] = StringUtils.s2b(Integer + .toString(DatabaseMetaData.procedureNullableUnknown), + this.connection); // nullable + + row[12] = null; + + resultRows.add(new ByteArrayRow(row, getExceptionInterceptor())); + } + + java.sql.ResultSet paramTypesRs = DatabaseMetaData.buildResultSet( + fields, resultRows, this.connection); + + convertGetProcedureColumnsToInternalDescriptors(paramTypesRs); } - - ArrayList resultRows = new ArrayList(); - - for (int i = 0; i < this.parameterCount; i++) { - byte[][] row = new byte[13][]; - row[0] = null; // PROCEDURE_CAT - row[1] = null; // PROCEDURE_SCHEM - row[2] = procNameAsBytes; // PROCEDURE/NAME - row[3] = StringUtils.s2b(String.valueOf(i), this.connection); // COLUMN_NAME - - row[4] = StringUtils.s2b(String - .valueOf(DatabaseMetaData.procedureColumnIn), - this.connection); - - row[5] = StringUtils.s2b(String.valueOf(Types.VARCHAR), - this.connection); // DATA_TYPE - row[6] = StringUtils.s2b("VARCHAR", this.connection); // TYPE_NAME - row[7] = StringUtils.s2b(Integer.toString(65535), this.connection); // PRECISION - row[8] = StringUtils.s2b(Integer.toString(65535), this.connection); // LENGTH - row[9] = StringUtils.s2b(Integer.toString(0), this.connection); // SCALE - row[10] = StringUtils.s2b(Integer.toString(10), this.connection); // RADIX - - row[11] = StringUtils.s2b(Integer - .toString(DatabaseMetaData.procedureNullableUnknown), - this.connection); // nullable - - row[12] = null; - - resultRows.add(row); - } - - java.sql.ResultSet paramTypesRs = DatabaseMetaData.buildResultSet( - fields, resultRows, this.connection); - - convertGetProcedureColumnsToInternalDescriptors(paramTypesRs); } private void determineParameterTypes() throws SQLException { - if (this.connection.getNoAccessToProcedureBodies()) { - fakeParameterTypes(); - - return; - } - - java.sql.ResultSet paramTypesRs = null; - - try { - String procName = extractProcedureName(); - - java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); - - boolean useCatalog = false; - - if (procName.indexOf(".") == -1) { - useCatalog = true; - } - - paramTypesRs = dbmd.getProcedureColumns(this.connection - .versionMeetsMinimum(5, 0, 2) - && useCatalog ? this.currentCatalog : null, null, procName, - "%"); //$NON-NLS-1$ - - convertGetProcedureColumnsToInternalDescriptors(paramTypesRs); - } finally { - SQLException sqlExRethrow = null; - - if (paramTypesRs != null) { + synchronized (checkClosed().getConnectionMutex()) { + java.sql.ResultSet paramTypesRs = null; + + try { + //Bug#57022, we need to check for db.SPname notation first + // and pass on only SPname + String procName = extractProcedureName(); + String quotedId = ""; try { - paramTypesRs.close(); + quotedId = this.connection.supportsQuotedIdentifiers() ? + this.connection.getMetaData().getIdentifierQuoteString() : ""; } catch (SQLException sqlEx) { - sqlExRethrow = sqlEx; + // Forced by API, never thrown from getIdentifierQuoteString() in + // this implementation. + AssertionFailedException.shouldNotHappen(sqlEx); } - - paramTypesRs = null; + + List parseList = StringUtils.splitDBdotName(procName, "", + quotedId , this.connection.isNoBackslashEscapesSet()); + String tmpCatalog = ""; + //There *should* be 2 rows, if any. + if (parseList.size() == 2) { + tmpCatalog = (String) parseList.get(0); + procName = (String) parseList.get(1); + } else { + //keep values as they are + } + + java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); + + boolean useCatalog = false; + + if (tmpCatalog.length() <= 0) { + useCatalog = true; + } + + paramTypesRs = dbmd.getProcedureColumns(this.connection + .versionMeetsMinimum(5, 0, 2) + && useCatalog ? this.currentCatalog : tmpCatalog/*null*/, null, procName, + "%"); //$NON-NLS-1$ + + boolean hasResults = false; + try { + if (paramTypesRs.next()) { + paramTypesRs.previous(); + hasResults = true; + } + } catch (Exception e) { + // paramTypesRs is empty, proceed with fake params. swallow, was expected + } + if (hasResults){ + convertGetProcedureColumnsToInternalDescriptors(paramTypesRs); + } else { + fakeParameterTypes(true); + } + } finally { + SQLException sqlExRethrow = null; + + if (paramTypesRs != null) { + try { + paramTypesRs.close(); + } catch (SQLException sqlEx) { + sqlExRethrow = sqlEx; + } + + paramTypesRs = null; + } + + if (sqlExRethrow != null) { + throw sqlExRethrow; + } } - - if (sqlExRethrow != null) { - throw sqlExRethrow; - } } } private void convertGetProcedureColumnsToInternalDescriptors(java.sql.ResultSet paramTypesRs) throws SQLException { - if (!this.connection.isRunningOnJDK13()) { - this.paramInfo = new CallableStatementParamInfoJDBC3( - paramTypesRs); - } else { - this.paramInfo = new CallableStatementParamInfo(paramTypesRs); + synchronized (checkClosed().getConnectionMutex()) { + if (!this.connection.isRunningOnJDK13()) { + this.paramInfo = new CallableStatementParamInfoJDBC3( + paramTypesRs); + } else { + this.paramInfo = new CallableStatementParamInfo(paramTypesRs); + } } } @@ -746,13 +910,11 @@ * @see java.sql.PreparedStatement#execute() */ public boolean execute() throws SQLException { - boolean returnVal = false; + synchronized (checkClosed().getConnectionMutex()) { + boolean returnVal = false; - checkClosed(); + checkStreamability(); - checkStreamability(); - - synchronized (this.connection.getMutex()) { setInOutParamsOnServer(); setOutParams(); @@ -765,14 +927,15 @@ } retrieveOutParams(); - } + - if (!this.callingStoredFunction) { - return returnVal; + if (!this.callingStoredFunction) { + return returnVal; + } + + // Functions can't return results + return false; } - - // Functions can't return results - return false; } /* @@ -781,22 +944,21 @@ * @see java.sql.PreparedStatement#executeQuery() */ public java.sql.ResultSet executeQuery() throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - checkStreamability(); + checkStreamability(); + + java.sql.ResultSet execResults = null; - java.sql.ResultSet execResults = null; - - synchronized (this.connection.getMutex()) { setInOutParamsOnServer(); setOutParams(); execResults = super.executeQuery(); retrieveOutParams(); + + return execResults; } - - return execResults; } /* @@ -805,28 +967,27 @@ * @see java.sql.PreparedStatement#executeUpdate() */ public int executeUpdate() throws SQLException { - int returnVal = -1; + synchronized (checkClosed().getConnectionMutex()) { + int returnVal = -1; + + + checkStreamability(); + + if (this.callingStoredFunction) { + execute(); + + return -1; + } - checkClosed(); - - checkStreamability(); - - if (this.callingStoredFunction) { - execute(); - - return -1; - } - - synchronized (this.connection.getMutex()) { setInOutParamsOnServer(); setOutParams(); returnVal = super.executeUpdate(); retrieveOutParams(); - } - return returnVal; + return returnVal; + } } private String extractProcedureName() throws SQLException { @@ -866,7 +1027,7 @@ } throw SQLError.createSQLException(Messages.getString("CallableStatement.1"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } /** @@ -880,70 +1041,76 @@ * @throws SQLException * if the parameter name is null or empty. */ - private String fixParameterName(String paramNameIn) throws SQLException { - if ((paramNameIn == null) || (paramNameIn.length() == 0)) { - throw SQLError.createSQLException( - ((Messages.getString("CallableStatement.0") + paramNameIn) == null) //$NON-NLS-1$ - ? Messages.getString("CallableStatement.15") : Messages.getString("CallableStatement.16"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ + protected String fixParameterName(String paramNameIn) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + //Fixed for 5.5+ + if (((paramNameIn == null) || (paramNameIn.length() == 0)) && (!hasParametersView())) { + throw SQLError.createSQLException( + ((Messages.getString("CallableStatement.0") + paramNameIn) == null) //$NON-NLS-1$ + ? Messages.getString("CallableStatement.15") : Messages.getString("CallableStatement.16"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if ((paramNameIn == null) && (hasParametersView())) { + paramNameIn = "nullpn"; + }; + + if (this.connection.getNoAccessToProcedureBodies()) { + throw SQLError.createSQLException("No access to parameters by name when connection has been configured not to access procedure bodies", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return mangleParameterName(paramNameIn); } - - if (this.connection.getNoAccessToProcedureBodies()) { - throw SQLError.createSQLException("No access to parameters by name when connection has been configured not to access procedure bodies", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - return mangleParameterName(paramNameIn); - - /* - * if (paramNameIn.startsWith("@")) { return paramNameIn; } else { - * StringBuffer paramNameBuf = new StringBuffer("@"); - * paramNameBuf.append(paramNameIn); - * - * return paramNameBuf.toString(); } - */ } /** * @see java.sql.CallableStatement#getArray(int) */ - public synchronized Array getArray(int i) throws SQLException { - ResultSet rs = getOutputParameters(i); - - Array retValue = rs.getArray(mapOutputParameterIndexToRsIndex(i)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Array getArray(int i) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(i); + + Array retValue = rs.getArray(mapOutputParameterIndexToRsIndex(i)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getArray(java.lang.String) */ - public synchronized Array getArray(String parameterName) + public Array getArray(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Array retValue = rs.getArray(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Array retValue = rs.getArray(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBigDecimal(int) */ - public synchronized BigDecimal getBigDecimal(int parameterIndex) + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - BigDecimal retValue = rs - .getBigDecimal(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + BigDecimal retValue = rs + .getBigDecimal(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** @@ -962,456 +1129,543 @@ * @see java.sql.CallableStatement#getBigDecimal(int, int) * @deprecated */ - public synchronized BigDecimal getBigDecimal(int parameterIndex, int scale) + public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - BigDecimal retValue = rs.getBigDecimal( - mapOutputParameterIndexToRsIndex(parameterIndex), scale); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + BigDecimal retValue = rs.getBigDecimal( + mapOutputParameterIndexToRsIndex(parameterIndex), scale); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBigDecimal(java.lang.String) */ - public synchronized BigDecimal getBigDecimal(String parameterName) + public BigDecimal getBigDecimal(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - BigDecimal retValue = rs.getBigDecimal(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + BigDecimal retValue = rs.getBigDecimal(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBlob(int) */ - public synchronized Blob getBlob(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Blob retValue = rs - .getBlob(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Blob getBlob(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Blob retValue = rs + .getBlob(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBlob(java.lang.String) */ - public synchronized Blob getBlob(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Blob retValue = rs.getBlob(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Blob getBlob(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Blob retValue = rs.getBlob(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBoolean(int) */ - public synchronized boolean getBoolean(int parameterIndex) + public boolean getBoolean(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - boolean retValue = rs - .getBoolean(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + boolean retValue = rs + .getBoolean(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBoolean(java.lang.String) */ - public synchronized boolean getBoolean(String parameterName) + public boolean getBoolean(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - boolean retValue = rs.getBoolean(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + boolean retValue = rs.getBoolean(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getByte(int) */ - public synchronized byte getByte(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - byte retValue = rs - .getByte(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public byte getByte(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + byte retValue = rs + .getByte(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getByte(java.lang.String) */ - public synchronized byte getByte(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - byte retValue = rs.getByte(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public byte getByte(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + byte retValue = rs.getByte(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBytes(int) */ - public synchronized byte[] getBytes(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - byte[] retValue = rs - .getBytes(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public byte[] getBytes(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + byte[] retValue = rs + .getBytes(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getBytes(java.lang.String) */ - public synchronized byte[] getBytes(String parameterName) + public byte[] getBytes(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - byte[] retValue = rs.getBytes(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + byte[] retValue = rs.getBytes(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getClob(int) */ - public synchronized Clob getClob(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Clob retValue = rs - .getClob(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Clob getClob(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Clob retValue = rs + .getClob(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getClob(java.lang.String) */ - public synchronized Clob getClob(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Clob retValue = rs.getClob(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Clob getClob(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Clob retValue = rs.getClob(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getDate(int) */ - public synchronized Date getDate(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Date retValue = rs - .getDate(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Date getDate(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Date retValue = rs + .getDate(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getDate(int, java.util.Calendar) */ - public synchronized Date getDate(int parameterIndex, Calendar cal) + public Date getDate(int parameterIndex, Calendar cal) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Date retValue = rs.getDate( - mapOutputParameterIndexToRsIndex(parameterIndex), cal); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Date retValue = rs.getDate( + mapOutputParameterIndexToRsIndex(parameterIndex), cal); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getDate(java.lang.String) */ - public synchronized Date getDate(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Date retValue = rs.getDate(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Date getDate(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Date retValue = rs.getDate(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getDate(java.lang.String, * java.util.Calendar) */ - public synchronized Date getDate(String parameterName, Calendar cal) + public Date getDate(String parameterName, Calendar cal) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Date retValue = rs.getDate(fixParameterName(parameterName), cal); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Date retValue = rs.getDate(fixParameterName(parameterName), cal); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getDouble(int) */ - public synchronized double getDouble(int parameterIndex) + public double getDouble(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - double retValue = rs - .getDouble(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + double retValue = rs + .getDouble(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getDouble(java.lang.String) */ - public synchronized double getDouble(String parameterName) + public double getDouble(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - double retValue = rs.getDouble(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + double retValue = rs.getDouble(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getFloat(int) */ - public synchronized float getFloat(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - float retValue = rs - .getFloat(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public float getFloat(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + float retValue = rs + .getFloat(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getFloat(java.lang.String) */ - public synchronized float getFloat(String parameterName) + public float getFloat(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - float retValue = rs.getFloat(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + float retValue = rs.getFloat(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getInt(int) */ - public synchronized int getInt(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - int retValue = rs - .getInt(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public int getInt(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + int retValue = rs + .getInt(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getInt(java.lang.String) */ - public synchronized int getInt(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - int retValue = rs.getInt(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public int getInt(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + int retValue = rs.getInt(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getLong(int) */ - public synchronized long getLong(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - long retValue = rs - .getLong(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public long getLong(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + long retValue = rs + .getLong(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getLong(java.lang.String) */ - public synchronized long getLong(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - long retValue = rs.getLong(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public long getLong(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + long retValue = rs.getLong(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } - private int getNamedParamIndex(String paramName, boolean forOut) + protected int getNamedParamIndex(String paramName, boolean forOut) throws SQLException { - if (this.connection.getNoAccessToProcedureBodies()) { - throw SQLError.createSQLException("No access to parameters by name when connection has been configured not to access procedure bodies", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - if ((paramName == null) || (paramName.length() == 0)) { - throw SQLError.createSQLException(Messages.getString("CallableStatement.2"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - CallableStatementParam namedParamInfo = this.paramInfo - .getParameter(paramName); - - if (this.paramInfo == null) { - throw SQLError.createSQLException( - Messages.getString("CallableStatement.3") + paramName + Messages.getString("CallableStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - if (forOut && !namedParamInfo.isOut) { - throw SQLError.createSQLException( - Messages.getString("CallableStatement.5") + paramName //$NON-NLS-1$ - + Messages.getString("CallableStatement.6"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - - if (this.placeholderToParameterIndexMap == null) { - return namedParamInfo.index + 1; // JDBC indices are 1-based - } - - for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) { - if (this.placeholderToParameterIndexMap[i] == namedParamInfo.index) { - return i + 1; + synchronized (checkClosed().getConnectionMutex()) { + if (this.connection.getNoAccessToProcedureBodies()) { + throw SQLError.createSQLException("No access to parameters by name when connection has been configured not to access procedure bodies", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } + + //Fixed for 5.5+ in callers + if ((paramName == null) || (paramName.length() == 0)) { + throw SQLError.createSQLException(Messages.getString("CallableStatement.2"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (this.paramInfo == null) { + throw SQLError.createSQLException( + Messages.getString("CallableStatement.3") + paramName + Messages.getString("CallableStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + CallableStatementParam namedParamInfo = this.paramInfo + .getParameter(paramName); + + if (forOut && !namedParamInfo.isOut) { + throw SQLError.createSQLException( + Messages.getString("CallableStatement.5") + paramName //$NON-NLS-1$ + + Messages.getString("CallableStatement.6"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + + if (this.placeholderToParameterIndexMap == null) { + return namedParamInfo.index + 1; // JDBC indices are 1-based + } + + for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) { + if (this.placeholderToParameterIndexMap[i] == namedParamInfo.index) { + return i + 1; + } + } + + throw SQLError.createSQLException("Can't find local placeholder mapping for parameter named \"" + + paramName + "\".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - - throw SQLError.createSQLException("Can't find local placeholder mapping for parameter named \"" + - paramName + "\".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } /** * @see java.sql.CallableStatement#getObject(int) */ - public synchronized Object getObject(int parameterIndex) + public Object getObject(int parameterIndex) throws SQLException { - CallableStatementParam paramDescriptor = checkIsOutputParam(parameterIndex); - - ResultSet rs = getOutputParameters(parameterIndex); - - Object retVal = rs.getObjectStoredProc( - mapOutputParameterIndexToRsIndex(parameterIndex), - paramDescriptor.desiredJdbcType); - - this.outputParamWasNull = rs.wasNull(); - - return retVal; + synchronized (checkClosed().getConnectionMutex()) { + CallableStatementParam paramDescriptor = checkIsOutputParam(parameterIndex); + + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Object retVal = rs.getObjectStoredProc( + mapOutputParameterIndexToRsIndex(parameterIndex), + paramDescriptor.desiredJdbcType); + + this.outputParamWasNull = rs.wasNull(); + + return retVal; + } } /** * @see java.sql.CallableStatement#getObject(int, java.util.Map) */ - public synchronized Object getObject(int parameterIndex, Map map) + public Object getObject(int parameterIndex, Map> map) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Object retVal = rs.getObject( - mapOutputParameterIndexToRsIndex(parameterIndex), map); - - this.outputParamWasNull = rs.wasNull(); - - return retVal; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Object retVal = rs.getObject( + mapOutputParameterIndexToRsIndex(parameterIndex), map); + + this.outputParamWasNull = rs.wasNull(); + + return retVal; + } } /** * @see java.sql.CallableStatement#getObject(java.lang.String) */ - public synchronized Object getObject(String parameterName) + public Object getObject(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Object retValue = rs.getObject(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Object retValue = rs.getObject(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getObject(java.lang.String, * java.util.Map) */ - public synchronized Object getObject(String parameterName, Map map) + public Object getObject(String parameterName, Map> map) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Object retValue = rs.getObject(fixParameterName(parameterName), map); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Object retValue = rs.getObject(fixParameterName(parameterName), map); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } + + // JDBC-4.1 + public T getObject(int parameterIndex, Class type) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + // remove cast once 1.5, 1.6 EOL'd + T retVal = ((ResultSetImpl)rs).getObject( + mapOutputParameterIndexToRsIndex(parameterIndex), type); + + this.outputParamWasNull = rs.wasNull(); + + return retVal; + } + } + + public T getObject(String parameterName, Class type) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + T retValue = ((ResultSetImpl)rs).getObject(fixParameterName(parameterName), type); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + } /** * Returns the ResultSet that holds the output parameters, or throws an @@ -1423,298 +1677,335 @@ * if no output parameters were defined, or if no output * parameters were returned. */ - private ResultSet getOutputParameters(int paramIndex) throws SQLException { - this.outputParamWasNull = false; - - if (paramIndex == 1 && this.callingStoredFunction - && this.returnValueParam != null) { - return this.functionReturnValueResults; - } - - if (this.outputParameterResults == null) { - if (this.paramInfo.numberOfParameters() == 0) { - throw SQLError.createSQLException(Messages - .getString("CallableStatement.7"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + protected ResultSetInternalMethods getOutputParameters(int paramIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.outputParamWasNull = false; + + if (paramIndex == 1 && this.callingStoredFunction + && this.returnValueParam != null) { + return this.functionReturnValueResults; } - throw SQLError.createSQLException(Messages.getString("CallableStatement.8"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + + if (this.outputParameterResults == null) { + if (this.paramInfo.numberOfParameters() == 0) { + throw SQLError.createSQLException(Messages + .getString("CallableStatement.7"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + throw SQLError.createSQLException(Messages.getString("CallableStatement.8"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + + return this.outputParameterResults; } - - return this.outputParameterResults; - } - public synchronized ParameterMetaData getParameterMetaData() + public ParameterMetaData getParameterMetaData() throws SQLException { - if (this.placeholderToParameterIndexMap == null) { - return (CallableStatementParamInfoJDBC3) this.paramInfo; - } else { + synchronized (checkClosed().getConnectionMutex()) { + if (this.placeholderToParameterIndexMap == null) { + return (CallableStatementParamInfoJDBC3) this.paramInfo; + } + return new CallableStatementParamInfoJDBC3(this.paramInfo); } } /** * @see java.sql.CallableStatement#getRef(int) */ - public synchronized Ref getRef(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Ref retValue = rs - .getRef(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Ref getRef(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Ref retValue = rs + .getRef(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getRef(java.lang.String) */ - public synchronized Ref getRef(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Ref retValue = rs.getRef(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Ref getRef(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Ref retValue = rs.getRef(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getShort(int) */ - public synchronized short getShort(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - short retValue = rs - .getShort(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public short getShort(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + short retValue = rs + .getShort(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getShort(java.lang.String) */ - public synchronized short getShort(String parameterName) + public short getShort(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - short retValue = rs.getShort(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + short retValue = rs.getShort(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getString(int) */ - public synchronized String getString(int parameterIndex) + public String getString(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - String retValue = rs - .getString(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + String retValue = rs + .getString(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getString(java.lang.String) */ - public synchronized String getString(String parameterName) + public String getString(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - String retValue = rs.getString(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + String retValue = rs.getString(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTime(int) */ - public synchronized Time getTime(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Time retValue = rs - .getTime(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Time getTime(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Time retValue = rs + .getTime(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTime(int, java.util.Calendar) */ - public synchronized Time getTime(int parameterIndex, Calendar cal) + public Time getTime(int parameterIndex, Calendar cal) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Time retValue = rs.getTime( - mapOutputParameterIndexToRsIndex(parameterIndex), cal); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Time retValue = rs.getTime( + mapOutputParameterIndexToRsIndex(parameterIndex), cal); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTime(java.lang.String) */ - public synchronized Time getTime(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Time retValue = rs.getTime(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public Time getTime(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Time retValue = rs.getTime(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTime(java.lang.String, * java.util.Calendar) */ - public synchronized Time getTime(String parameterName, Calendar cal) + public Time getTime(String parameterName, Calendar cal) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Time retValue = rs.getTime(fixParameterName(parameterName), cal); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Time retValue = rs.getTime(fixParameterName(parameterName), cal); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTimestamp(int) */ - public synchronized Timestamp getTimestamp(int parameterIndex) + public Timestamp getTimestamp(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Timestamp retValue = rs - .getTimestamp(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Timestamp retValue = rs + .getTimestamp(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTimestamp(int, java.util.Calendar) */ - public synchronized Timestamp getTimestamp(int parameterIndex, Calendar cal) + public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - Timestamp retValue = rs.getTimestamp( - mapOutputParameterIndexToRsIndex(parameterIndex), cal); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Timestamp retValue = rs.getTimestamp( + mapOutputParameterIndexToRsIndex(parameterIndex), cal); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTimestamp(java.lang.String) */ - public synchronized Timestamp getTimestamp(String parameterName) + public Timestamp getTimestamp(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Timestamp retValue = rs.getTimestamp(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Timestamp retValue = rs.getTimestamp(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getTimestamp(java.lang.String, * java.util.Calendar) */ - public synchronized Timestamp getTimestamp(String parameterName, + public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - Timestamp retValue = rs.getTimestamp(fixParameterName(parameterName), - cal); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + Timestamp retValue = rs.getTimestamp(fixParameterName(parameterName), + cal); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getURL(int) */ - public synchronized URL getURL(int parameterIndex) throws SQLException { - ResultSet rs = getOutputParameters(parameterIndex); - - URL retValue = rs - .getURL(mapOutputParameterIndexToRsIndex(parameterIndex)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public URL getURL(int parameterIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + URL retValue = rs + .getURL(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } /** * @see java.sql.CallableStatement#getURL(java.lang.String) */ - public synchronized URL getURL(String parameterName) throws SQLException { - ResultSet rs = getOutputParameters(0); // definitely not going to be - // from ?= - - URL retValue = rs.getURL(fixParameterName(parameterName)); - - this.outputParamWasNull = rs.wasNull(); - - return retValue; + public URL getURL(String parameterName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be + // from ?= + + URL retValue = rs.getURL(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } } - private int mapOutputParameterIndexToRsIndex(int paramIndex) + protected int mapOutputParameterIndexToRsIndex(int paramIndex) throws SQLException { - if (this.returnValueParam != null && paramIndex == 1) { - return 1; + synchronized (checkClosed().getConnectionMutex()) { + if (this.returnValueParam != null && paramIndex == 1) { + return 1; + } + + checkParameterIndexBounds(paramIndex); + + int localParamIndex = paramIndex - 1; + + if (this.placeholderToParameterIndexMap != null) { + localParamIndex = this.placeholderToParameterIndexMap[localParamIndex]; + } + + int rsIndex = this.parameterIndexToRsIndex[localParamIndex]; + + if (rsIndex == NOT_OUTPUT_PARAMETER_INDICATOR) { + throw SQLError.createSQLException( + Messages.getString("CallableStatement.21") + paramIndex //$NON-NLS-1$ + + Messages.getString("CallableStatement.22"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return rsIndex + 1; } - - checkParameterIndexBounds(paramIndex); - - int localParamIndex = paramIndex - 1; - - if (this.placeholderToParameterIndexMap != null) { - localParamIndex = this.placeholderToParameterIndexMap[localParamIndex]; - } - - int rsIndex = this.parameterIndexToRsIndex[localParamIndex]; - - if (rsIndex == NOT_OUTPUT_PARAMETER_INDICATOR) { - throw SQLError.createSQLException( - Messages.getString("CallableStatement.21") + paramIndex //$NON-NLS-1$ - + Messages.getString("CallableStatement.22"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - return rsIndex + 1; } /** @@ -1747,9 +2038,11 @@ * @see java.sql.CallableStatement#registerOutParameter(java.lang.String, * int) */ - public synchronized void registerOutParameter(String parameterName, + public void registerOutParameter(String parameterName, int sqlType) throws SQLException { - registerOutParameter(getNamedParamIndex(parameterName, true), sqlType); + synchronized (checkClosed().getConnectionMutex()) { + registerOutParameter(getNamedParamIndex(parameterName, true), sqlType); + } } /** @@ -1778,75 +2071,81 @@ * if an error occurs. */ private void retrieveOutParams() throws SQLException { - int numParameters = this.paramInfo.numberOfParameters(); - - this.parameterIndexToRsIndex = new int[numParameters]; - - for (int i = 0; i < numParameters; i++) { - this.parameterIndexToRsIndex[i] = NOT_OUTPUT_PARAMETER_INDICATOR; - } - - int localParamIndex = 0; - - if (numParameters > 0) { - StringBuffer outParameterQuery = new StringBuffer("SELECT "); //$NON-NLS-1$ - - boolean firstParam = true; - boolean hadOutputParams = false; - - for (Iterator paramIter = this.paramInfo.iterator(); paramIter - .hasNext();) { - CallableStatementParam retrParamInfo = (CallableStatementParam) paramIter - .next(); - - if (retrParamInfo.isOut) { - hadOutputParams = true; - - this.parameterIndexToRsIndex[retrParamInfo.index] = localParamIndex++; - - String outParameterName = mangleParameterName(retrParamInfo.paramName); - - if (!firstParam) { - outParameterQuery.append(","); //$NON-NLS-1$ - } else { - firstParam = false; + synchronized (checkClosed().getConnectionMutex()) { + int numParameters = this.paramInfo.numberOfParameters(); + + this.parameterIndexToRsIndex = new int[numParameters]; + + for (int i = 0; i < numParameters; i++) { + this.parameterIndexToRsIndex[i] = NOT_OUTPUT_PARAMETER_INDICATOR; + } + + int localParamIndex = 0; + + if (numParameters > 0) { + StringBuffer outParameterQuery = new StringBuffer("SELECT "); //$NON-NLS-1$ + + boolean firstParam = true; + boolean hadOutputParams = false; + + for (Iterator paramIter = this.paramInfo.iterator(); paramIter + .hasNext();) { + CallableStatementParam retrParamInfo = paramIter + .next(); + + if (retrParamInfo.isOut) { + hadOutputParams = true; + + this.parameterIndexToRsIndex[retrParamInfo.index] = localParamIndex++; + + if ((retrParamInfo.paramName == null) && (hasParametersView())) { + retrParamInfo.paramName = "nullnp" + retrParamInfo.index; + } + + String outParameterName = mangleParameterName(retrParamInfo.paramName); + + if (!firstParam) { + outParameterQuery.append(","); //$NON-NLS-1$ + } else { + firstParam = false; + } + + if (!outParameterName.startsWith("@")) { //$NON-NLS-1$ + outParameterQuery.append('@'); + } + + outParameterQuery.append(outParameterName); } - - if (!outParameterName.startsWith("@")) { //$NON-NLS-1$ - outParameterQuery.append('@'); - } - - outParameterQuery.append(outParameterName); } - } - - if (hadOutputParams) { - // We can't use 'ourself' to execute this query, or any - // pending result sets would be overwritten - java.sql.Statement outParameterStmt = null; - java.sql.ResultSet outParamRs = null; - - try { - outParameterStmt = this.connection.createStatement(); - outParamRs = outParameterStmt - .executeQuery(outParameterQuery.toString()); - this.outputParameterResults = ((com.mysql.jdbc.ResultSet) outParamRs) - .copy(); - - if (!this.outputParameterResults.next()) { - this.outputParameterResults.close(); - this.outputParameterResults = null; + + if (hadOutputParams) { + // We can't use 'ourself' to execute this query, or any + // pending result sets would be overwritten + java.sql.Statement outParameterStmt = null; + java.sql.ResultSet outParamRs = null; + + try { + outParameterStmt = this.connection.createStatement(); + outParamRs = outParameterStmt + .executeQuery(outParameterQuery.toString()); + this.outputParameterResults = ((com.mysql.jdbc.ResultSetInternalMethods) outParamRs) + .copy(); + + if (!this.outputParameterResults.next()) { + this.outputParameterResults.close(); + this.outputParameterResults = null; + } + } finally { + if (outParameterStmt != null) { + outParameterStmt.close(); + } } - } finally { - if (outParameterStmt != null) { - outParameterStmt.close(); - } + } else { + this.outputParameterResults = null; } } else { this.outputParameterResults = null; } - } else { - this.outputParameterResults = null; } } @@ -1942,75 +2241,83 @@ * */ private void setInOutParamsOnServer() throws SQLException { - if (this.paramInfo.numParameters > 0) { - int parameterIndex = 0; - - for (Iterator paramIter = this.paramInfo.iterator(); paramIter - .hasNext();) { - - CallableStatementParam inParamInfo = (CallableStatementParam) paramIter - .next(); - - if (inParamInfo.isOut && inParamInfo.isIn) { - String inOutParameterName = mangleParameterName(inParamInfo.paramName); - StringBuffer queryBuf = new StringBuffer( - 4 + inOutParameterName.length() + 1 + 1); - queryBuf.append("SET "); //$NON-NLS-1$ - queryBuf.append(inOutParameterName); - queryBuf.append("=?"); //$NON-NLS-1$ - - PreparedStatement setPstmt = null; - - try { - setPstmt = this.connection - .clientPrepareStatement(queryBuf.toString()); - - byte[] parameterAsBytes = getBytesRepresentation( - inParamInfo.index); - - if (parameterAsBytes != null) { - if (parameterAsBytes.length > 8 - && parameterAsBytes[0] == '_' - && parameterAsBytes[1] == 'b' - && parameterAsBytes[2] == 'i' - && parameterAsBytes[3] == 'n' - && parameterAsBytes[4] == 'a' - && parameterAsBytes[5] == 'r' - && parameterAsBytes[6] == 'y' - && parameterAsBytes[7] == '\'') { - setPstmt.setBytesNoEscapeNoQuotes(1, - parameterAsBytes); - } else { - int sqlType = inParamInfo.desiredJdbcType; + synchronized (checkClosed().getConnectionMutex()) { + if (this.paramInfo.numParameters > 0) { + for (Iterator paramIter = this.paramInfo.iterator(); paramIter + .hasNext();) { + + CallableStatementParam inParamInfo = paramIter + .next(); + + //Fix for 5.5+ + if (inParamInfo.isOut && inParamInfo.isIn) { + if ((inParamInfo.paramName == null) && (hasParametersView())) { + inParamInfo.paramName = "nullnp" + inParamInfo.index; + }; + + String inOutParameterName = mangleParameterName(inParamInfo.paramName); + StringBuffer queryBuf = new StringBuffer( + 4 + inOutParameterName.length() + 1 + 1); + queryBuf.append("SET "); //$NON-NLS-1$ + queryBuf.append(inOutParameterName); + queryBuf.append("=?"); //$NON-NLS-1$ + + PreparedStatement setPstmt = null; + + try { + setPstmt = (PreparedStatement) this.connection + .clientPrepareStatement(queryBuf.toString()); + + if (this.isNull[inParamInfo.index]) { + setPstmt.setBytesNoEscapeNoQuotes(1, "NULL".getBytes()); - switch (sqlType) { - case Types.BIT: - case Types.BINARY: - case Types.BLOB: - case Types.JAVA_OBJECT: - case Types.LONGVARBINARY: - case Types.VARBINARY: - setPstmt.setBytes(1, parameterAsBytes); - break; - default: - // the inherited PreparedStatement methods - // have already escaped and quoted these parameters - setPstmt.setBytesNoEscape(1, parameterAsBytes); + } else { + byte[] parameterAsBytes = getBytesRepresentation( + inParamInfo.index); + + if (parameterAsBytes != null) { + if (parameterAsBytes.length > 8 + && parameterAsBytes[0] == '_' + && parameterAsBytes[1] == 'b' + && parameterAsBytes[2] == 'i' + && parameterAsBytes[3] == 'n' + && parameterAsBytes[4] == 'a' + && parameterAsBytes[5] == 'r' + && parameterAsBytes[6] == 'y' + && parameterAsBytes[7] == '\'') { + setPstmt.setBytesNoEscapeNoQuotes(1, + parameterAsBytes); + } else { + int sqlType = inParamInfo.desiredJdbcType; + + switch (sqlType) { + case Types.BIT: + case Types.BINARY: + case Types.BLOB: + case Types.JAVA_OBJECT: + case Types.LONGVARBINARY: + case Types.VARBINARY: + setPstmt.setBytes(1, parameterAsBytes); + break; + default: + // the inherited PreparedStatement methods + // have already escaped and quoted these parameters + setPstmt.setBytesNoEscape(1, parameterAsBytes); + } + } + } else { + setPstmt.setNull(1, Types.NULL); } } - } else { - setPstmt.setNull(1, Types.NULL); + + setPstmt.executeUpdate(); + } finally { + if (setPstmt != null) { + setPstmt.close(); + } } - - setPstmt.executeUpdate(); - } finally { - if (setPstmt != null) { - setPstmt.close(); - } } } - - parameterIndex++; } } } @@ -2071,29 +2378,49 @@ } private void setOutParams() throws SQLException { - if (this.paramInfo.numParameters > 0) { - for (Iterator paramIter = this.paramInfo.iterator(); paramIter - .hasNext();) { - CallableStatementParam outParamInfo = (CallableStatementParam) paramIter - .next(); - - if (!this.callingStoredFunction && outParamInfo.isOut) { - String outParameterName = mangleParameterName(outParamInfo.paramName); - - int outParamIndex; - - if (this.placeholderToParameterIndexMap == null) { - outParamIndex = outParamInfo.index + 1; - } else { - outParamIndex = this.placeholderToParameterIndexMap[outParamInfo.index - 1 /* JDBC is 1-based */]; + synchronized (checkClosed().getConnectionMutex()) { + if (this.paramInfo.numParameters > 0) { + for (Iterator paramIter = this.paramInfo.iterator(); paramIter + .hasNext();) { + CallableStatementParam outParamInfo = paramIter + .next(); + + if (!this.callingStoredFunction && outParamInfo.isOut) { + + if ((outParamInfo.paramName == null) && (hasParametersView())) { + outParamInfo.paramName = "nullnp" + outParamInfo.index; + }; + + String outParameterName = mangleParameterName(outParamInfo.paramName); + + int outParamIndex = 0; + + if (this.placeholderToParameterIndexMap == null) { + outParamIndex = outParamInfo.index + 1; + } else { + // Find it, todo: remove this linear search + boolean found = false; + + for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) { + if (this.placeholderToParameterIndexMap[i] == outParamInfo.index) { + outParamIndex = i + 1; /* JDBC is 1-based */ + found = true; + break; + } + } + + if (!found) { + throw SQLError.createSQLException("boo!", "S1000", this.connection.getExceptionInterceptor()); + } + } + + this.setBytesNoEscapeNoQuotes(outParamIndex, + StringUtils.getBytes(outParameterName, + this.charConverter, this.charEncoding, + this.connection + .getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor())); } - - this.setBytesNoEscapeNoQuotes(outParamIndex, - StringUtils.getBytes(outParameterName, - this.charConverter, this.charEncoding, - this.connection - .getServerCharacterEncoding(), - this.connection.parserKnowsUnicode())); } } } @@ -2158,14 +2485,16 @@ /** * @see java.sql.CallableStatement#wasNull() */ - public synchronized boolean wasNull() throws SQLException { - return this.outputParamWasNull; + public boolean wasNull() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.outputParamWasNull; + } } public int[] executeBatch() throws SQLException { if (this.hasOutputParams) { throw SQLError.createSQLException("Can't call executeBatch() on CallableStatement with OUTPUT parameters", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } return super.executeBatch(); @@ -2178,4 +2507,168 @@ return super.getParameterIndexOffset(); } + + public void setAsciiStream(String parameterName, InputStream x) throws SQLException { + setAsciiStream(getNamedParamIndex(parameterName, false), x); + + } + + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { + setAsciiStream(getNamedParamIndex(parameterName, false), x, length); + + } + + public void setBinaryStream(String parameterName, InputStream x) throws SQLException { + setBinaryStream(getNamedParamIndex(parameterName, false), x); + + } + + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { + setBinaryStream(getNamedParamIndex(parameterName, false), x, length); + + } + + public void setBlob(String parameterName, Blob x) throws SQLException { + setBlob(getNamedParamIndex(parameterName, false), x); + + } + + public void setBlob(String parameterName, InputStream inputStream) throws SQLException { + setBlob(getNamedParamIndex(parameterName, false), inputStream); + + } + + public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { + setBlob(getNamedParamIndex(parameterName, false), inputStream, length); + + } + + public void setCharacterStream(String parameterName, Reader reader) throws SQLException { + setCharacterStream(getNamedParamIndex(parameterName, false), reader); + + } + + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + setCharacterStream(getNamedParamIndex(parameterName, false), reader, length); + + } + + public void setClob(String parameterName, Clob x) throws SQLException { + setClob(getNamedParamIndex(parameterName, false), x); + + } + + public void setClob(String parameterName, Reader reader) throws SQLException { + setClob(getNamedParamIndex(parameterName, false), reader); + + } + + public void setClob(String parameterName, Reader reader, long length) throws SQLException { + setClob(getNamedParamIndex(parameterName, false), reader, length); + + } + + public void setNCharacterStream(String parameterName, Reader value) throws SQLException { + setNCharacterStream(getNamedParamIndex(parameterName, false), value); + + } + + public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { + setNCharacterStream(getNamedParamIndex(parameterName, false), value, length); + + } + + /** + * Check whether the stored procedure alters any data or is safe for read-only usage. + * + * @return true if procedure does not alter data + * @throws SQLException + */ + private boolean checkReadOnlyProcedure() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.connection.getNoAccessToProcedureBodies()) { + return false; + } + + if (this.paramInfo.isReadOnlySafeChecked) { + return this.paramInfo.isReadOnlySafeProcedure; + } + + ResultSet rs = null; + java.sql.PreparedStatement ps = null; + + try { + String procName = extractProcedureName(); + + String catalog = this.currentCatalog; + + if (procName.indexOf(".") != -1) { + catalog = procName.substring(0, procName.indexOf(".")); + + if (StringUtils.startsWithIgnoreCaseAndWs(catalog, "`") && catalog.trim().endsWith("`")) { + catalog = catalog.substring(1, catalog.length() - 1); + } + + procName = procName.substring(procName.indexOf(".") + 1); + procName = StringUtils.toString(StringUtils.stripEnclosure( + StringUtils.getBytes(procName), "`", "`")); + } + ps = this.connection + .prepareStatement("SELECT SQL_DATA_ACCESS FROM " + + " information_schema.routines " + + " WHERE routine_schema = ? " + + " AND routine_name = ?"); + ps.setMaxRows(0); + ps.setFetchSize(0); + + ps.setString(1, catalog); + ps.setString(2, procName); + rs = ps.executeQuery(); + if (rs.next()) { + String sqlDataAccess = rs.getString(1); + if ("READS SQL DATA".equalsIgnoreCase(sqlDataAccess) + || "NO SQL".equalsIgnoreCase(sqlDataAccess)) { + synchronized (this.paramInfo) { + this.paramInfo.isReadOnlySafeChecked = true; + this.paramInfo.isReadOnlySafeProcedure = true; + } + return true; + } + } + } catch (SQLException e) { + // swallow the Exception + } finally { + if(rs != null){ + rs.close(); + } + if(ps != null){ + ps.close(); + } + + } + this.paramInfo.isReadOnlySafeChecked = false; + this.paramInfo.isReadOnlySafeProcedure = false; + } + return false; + + } + + protected boolean checkReadOnlySafeStatement() throws SQLException { + return (super.checkReadOnlySafeStatement() || this.checkReadOnlyProcedure()); + } + + private boolean hasParametersView() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + try { + if (this.connection.versionMeetsMinimum(5, 5, 0)) { + java.sql.DatabaseMetaData dbmd1 = new DatabaseMetaDataUsingInfoSchema(this.connection, this.connection.getCatalog()); + return ((DatabaseMetaDataUsingInfoSchema)dbmd1).gethasParametersView(); + } + + return false; + } catch (SQLException e) { + return false; + } + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CharsetMapping.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CharsetMapping.java (.../CharsetMapping.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CharsetMapping.java (.../CharsetMapping.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2006 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; @@ -51,71 +50,163 @@ * Map of MySQL-4.1 charset indexes to Java encoding names */ public static final String[] INDEX_TO_CHARSET; - + /** * Map of MySQL-4.1 collation index to collation names */ public static final String[] INDEX_TO_COLLATION; + /** + * Size of static maps INDEX_TO_JAVA_CHARSET, INDEX_TO_MYSQL_CHARSET, INDEX_TO_COLLATION + */ + public static final int MAP_SIZE = 255; + /** + * Map of MySQL-4.1 collation indexes to MySQL encoding names + */ + public static final Map STATIC_INDEX_TO_MYSQL_CHARSET_MAP; + /** + * Map of MySQL-4.1 charset names to mblen + */ + public static final Map STATIC_CHARSET_TO_NUM_BYTES_MAP; + /** + * Map of MySQL-4.0 charset names to mblen + */ + public static final Map STATIC_4_0_CHARSET_TO_NUM_BYTES_MAP; /** Mapping of Java charset names to MySQL charset names */ - private static final Map JAVA_TO_MYSQL_CHARSET_MAP; + private static final Map> JAVA_TO_MYSQL_CHARSET_MAP; - private static final Map JAVA_UC_TO_MYSQL_CHARSET_MAP; + private static final Map> JAVA_UC_TO_MYSQL_CHARSET_MAP; - private static final Map ERROR_MESSAGE_FILE_TO_MYSQL_CHARSET_MAP; + private static final Map ERROR_MESSAGE_FILE_TO_MYSQL_CHARSET_MAP; /** Map/List of multibyte character sets (using MySQL names) */ - private static final Map MULTIBYTE_CHARSETS; + private static final Map MULTIBYTE_CHARSETS; - private static final Map MYSQL_TO_JAVA_CHARSET_MAP; + public static final Map MYSQL_TO_JAVA_CHARSET_MAP; + private static final Map MYSQL_ENCODING_NAME_TO_CHARSET_INDEX_MAP; + + private static final String MYSQL_CHARSET_NAME_armscii8 = "armscii8"; + private static final String MYSQL_CHARSET_NAME_ascii = "ascii"; + private static final String MYSQL_CHARSET_NAME_big5 = "big5"; + private static final String MYSQL_CHARSET_NAME_binary = "binary"; + private static final String MYSQL_CHARSET_NAME_cp1250 = "cp1250"; + private static final String MYSQL_CHARSET_NAME_cp1251 = "cp1251"; + private static final String MYSQL_CHARSET_NAME_cp1256 = "cp1256"; + private static final String MYSQL_CHARSET_NAME_cp1257 = "cp1257"; + private static final String MYSQL_CHARSET_NAME_cp850 = "cp850"; + private static final String MYSQL_CHARSET_NAME_cp852 = "cp852"; + private static final String MYSQL_CHARSET_NAME_cp866 = "cp866"; + private static final String MYSQL_CHARSET_NAME_cp932 = "cp932"; + private static final String MYSQL_CHARSET_NAME_dec8 = "dec8"; + private static final String MYSQL_CHARSET_NAME_eucjpms = "eucjpms"; + private static final String MYSQL_CHARSET_NAME_euckr = "euckr"; + private static final String MYSQL_CHARSET_NAME_gb2312 = "gb2312"; + private static final String MYSQL_CHARSET_NAME_gbk = "gbk"; + private static final String MYSQL_CHARSET_NAME_geostd8 = "geostd8"; + private static final String MYSQL_CHARSET_NAME_greek = "greek"; + private static final String MYSQL_CHARSET_NAME_hebrew = "hebrew"; + private static final String MYSQL_CHARSET_NAME_hp8 = "hp8"; + private static final String MYSQL_CHARSET_NAME_keybcs2 = "keybcs2"; + private static final String MYSQL_CHARSET_NAME_koi8r = "koi8r"; + private static final String MYSQL_CHARSET_NAME_koi8u = "koi8u"; + private static final String MYSQL_CHARSET_NAME_latin1 = "latin1"; + private static final String MYSQL_CHARSET_NAME_latin2 = "latin2"; + private static final String MYSQL_CHARSET_NAME_latin5 = "latin5"; + private static final String MYSQL_CHARSET_NAME_latin7 = "latin7"; + private static final String MYSQL_CHARSET_NAME_macce = "macce"; + private static final String MYSQL_CHARSET_NAME_macroman = "macroman"; + private static final String MYSQL_CHARSET_NAME_sjis = "sjis"; + private static final String MYSQL_CHARSET_NAME_swe7 = "swe7"; + private static final String MYSQL_CHARSET_NAME_tis620 = "tis620"; + private static final String MYSQL_CHARSET_NAME_ucs2 = "ucs2"; + private static final String MYSQL_CHARSET_NAME_ujis = "ujis"; + private static final String MYSQL_CHARSET_NAME_utf16 = "utf16"; + private static final String MYSQL_CHARSET_NAME_utf16le = "utf16le"; + private static final String MYSQL_CHARSET_NAME_utf32 = "utf32"; + private static final String MYSQL_CHARSET_NAME_utf8 = "utf8"; + private static final String MYSQL_CHARSET_NAME_utf8mb4 = "utf8mb4"; + + private static final String MYSQL_4_0_CHARSET_NAME_croat = "croat"; // 4.1 => 27 latin2 latin2_croatian_ci + private static final String MYSQL_4_0_CHARSET_NAME_czech = "czech"; // 4.1 => 2 latin2 latin2_czech_ci + private static final String MYSQL_4_0_CHARSET_NAME_danish = "danish"; // 4.1 => 15 latin1 latin1_danish_ci + private static final String MYSQL_4_0_CHARSET_NAME_dos = "dos"; // 4.1 => 4 cp850 cp850_general_ci + private static final String MYSQL_4_0_CHARSET_NAME_estonia = "estonia"; // 4.1 => 20 latin7 latin7_estonian_ci + private static final String MYSQL_4_0_CHARSET_NAME_euc_kr = "euc_kr"; // 4.1 => 19 euckr euckr_korean_ci + private static final String MYSQL_4_0_CHARSET_NAME_german1 = "german1"; // 4.1 => 5 latin1 latin1_german1_ci + private static final String MYSQL_4_0_CHARSET_NAME_hungarian = "hungarian"; // 4.1 => 21 latin2 latin2_hungarian_ci + private static final String MYSQL_4_0_CHARSET_NAME_koi8_ru = "koi8_ru"; // 4.1 => 7 koi8r koi8r_general_ci + private static final String MYSQL_4_0_CHARSET_NAME_koi8_ukr = "koi8_ukr"; // 4.1 => 22 koi8u koi8u_ukrainian_ci + private static final String MYSQL_4_0_CHARSET_NAME_latin1_de = "latin1_de"; // 4.1 => 31 latin1 latin1_german2_ci + private static final String MYSQL_4_0_CHARSET_NAME_usa7 = "usa7"; // 4.1 => 11 ascii ascii_general_ci + private static final String MYSQL_4_0_CHARSET_NAME_win1250 = "win1250"; // 4.1 => 26 cp1250 cp1250_general_ci + private static final String MYSQL_4_0_CHARSET_NAME_win1251 = "win1251"; // 4.1 => 17 (removed) + private static final String MYSQL_4_0_CHARSET_NAME_win1251ukr = "win1251ukr"; // 4.1 => 23 cp1251 cp1251_ukrainian_ci + private static final String NOT_USED = "ISO8859_1"; // punting for not-used character sets - public static final Map STATIC_CHARSET_TO_NUM_BYTES_MAP; - - static { - HashMap tempNumBytesMap = new HashMap(); - - tempNumBytesMap.put("big5", new Integer(2)); - tempNumBytesMap.put("dec8" , new Integer(1)); - tempNumBytesMap.put("cp850", new Integer(1)); - tempNumBytesMap.put("hp8", new Integer(1)); - tempNumBytesMap.put("koi8r", new Integer(1)); - tempNumBytesMap.put("latin1", new Integer(1)); - tempNumBytesMap.put("latin2", new Integer(1)); - tempNumBytesMap.put("swe7", new Integer(1)); - tempNumBytesMap.put("ascii", new Integer(1)); - tempNumBytesMap.put("ujis", new Integer(3)); - tempNumBytesMap.put("sjis", new Integer(2)); - tempNumBytesMap.put("hebrew", new Integer(1)); - tempNumBytesMap.put("tis620", new Integer(1)); - tempNumBytesMap.put("euckr", new Integer(2)); - tempNumBytesMap.put("koi8u", new Integer(1)); - tempNumBytesMap.put("gb2312", new Integer(2)); - tempNumBytesMap.put("greek", new Integer(1)); - tempNumBytesMap.put("cp1250", new Integer(1)); - tempNumBytesMap.put("gbk", new Integer(2)); - tempNumBytesMap.put("latin5", new Integer(1)); - tempNumBytesMap.put("armscii8", new Integer(1)); - tempNumBytesMap.put("utf8", new Integer(3)); - tempNumBytesMap.put("ucs2", new Integer(2)); - tempNumBytesMap.put("cp866", new Integer(1)); - tempNumBytesMap.put("keybcs2", new Integer(1)); - tempNumBytesMap.put("macce", new Integer(1)); - tempNumBytesMap.put("macroman", new Integer(1)); - tempNumBytesMap.put("cp852" , new Integer(1)); - tempNumBytesMap.put("latin7", new Integer(1)); - tempNumBytesMap.put("cp1251", new Integer(1)); - tempNumBytesMap.put("cp1256" , new Integer(1)); - tempNumBytesMap.put("cp1257", new Integer(1)); - tempNumBytesMap.put("binary", new Integer(1)); - tempNumBytesMap.put("geostd8", new Integer(1)); - tempNumBytesMap.put("cp932", new Integer(2)); - tempNumBytesMap.put("eucjpms", new Integer(3)); - - STATIC_CHARSET_TO_NUM_BYTES_MAP = Collections.unmodifiableMap( - tempNumBytesMap); + static { + HashMap tempNumBytesMap = new HashMap(); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_armscii8, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_ascii, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_big5, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_binary, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp1250, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp1251, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp1256, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp1257, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp850, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp852, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp866, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_cp932, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_dec8, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_eucjpms, 3); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_euckr, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_gb2312, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_gbk, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_geostd8, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_greek, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_hebrew, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_hp8, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_keybcs2, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_koi8r, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_koi8u, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_latin1, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_latin2, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_latin5, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_latin7, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_macce, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_macroman, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_sjis, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_swe7, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_tis620, 1); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_ucs2, 2); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_ujis, 3); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_utf16, 4); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_utf16le, 4); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_utf32, 4); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_utf8, 3); + tempNumBytesMap.put(MYSQL_CHARSET_NAME_utf8mb4, 4); + STATIC_CHARSET_TO_NUM_BYTES_MAP = Collections.unmodifiableMap(tempNumBytesMap); + tempNumBytesMap = new HashMap(); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_croat, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_czech, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_danish, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_dos, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_estonia, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_euc_kr, 2); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_german1, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_hungarian, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_koi8_ru, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_koi8_ukr, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_latin1_de, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_usa7, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_win1250, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_win1251, 1); + tempNumBytesMap.put(MYSQL_4_0_CHARSET_NAME_win1251ukr, 1); + STATIC_4_0_CHARSET_TO_NUM_BYTES_MAP = Collections.unmodifiableMap(tempNumBytesMap); + CHARSET_CONFIG.setProperty("javaToMysqlMappings", // // Note: This used to be stored in Charsets.properties, @@ -172,6 +263,7 @@ + "MacRoman = macroman," + "MacCentralEurope = macce," + "UTF-8 = utf8," + + "UTF-8 = *> 5.5.2 utf8mb4," + "UnicodeBig = ucs2," + "US-ASCII = binary," + "Cp943 = sjis," @@ -189,37 +281,35 @@ + "GREEK = greek," + "EUCKR = euckr," + "GB2312 = gb2312," - + "LATIN2 = latin2"); + + "LATIN2 = latin2," + + "UTF-16 = >5.2.0 utf16," + + "UTF-16LE = >5.6.0 utf16le," + + "UTF-32 = >5.2.0 utf32"); - HashMap javaToMysqlMap = new HashMap(); + HashMap> javaToMysqlMap = new HashMap>(); - populateMapWithKeyValuePairs("javaToMysqlMappings", javaToMysqlMap, - true, false); + populateMapWithKeyValuePairsVersioned("javaToMysqlMappings", javaToMysqlMap, false); JAVA_TO_MYSQL_CHARSET_MAP = Collections.unmodifiableMap(javaToMysqlMap); - HashMap mysqlToJavaMap = new HashMap(); - Set keySet = JAVA_TO_MYSQL_CHARSET_MAP.keySet(); + HashMap mysqlToJavaMap = new HashMap(); - Iterator javaCharsets = keySet.iterator(); - + Set keySet = JAVA_TO_MYSQL_CHARSET_MAP.keySet(); + Iterator javaCharsets = keySet.iterator(); while (javaCharsets.hasNext()) { - Object javaEncodingName = javaCharsets.next(); - List mysqlEncodingList = (List) JAVA_TO_MYSQL_CHARSET_MAP - .get(javaEncodingName); + String javaEncodingName = javaCharsets.next(); + List mysqlEncodingList = JAVA_TO_MYSQL_CHARSET_MAP.get(javaEncodingName); - Iterator mysqlEncodings = mysqlEncodingList.iterator(); + Iterator mysqlEncodings = mysqlEncodingList.iterator(); String mysqlEncodingName = null; while (mysqlEncodings.hasNext()) { - VersionedStringProperty mysqlProp = (VersionedStringProperty) mysqlEncodings - .next(); + VersionedStringProperty mysqlProp = mysqlEncodings.next(); mysqlEncodingName = mysqlProp.toString(); mysqlToJavaMap.put(mysqlEncodingName, javaEncodingName); - mysqlToJavaMap.put(mysqlEncodingName - .toUpperCase(Locale.ENGLISH), javaEncodingName); + mysqlToJavaMap.put(mysqlEncodingName.toUpperCase(Locale.ENGLISH), javaEncodingName); } } @@ -229,24 +319,20 @@ MYSQL_TO_JAVA_CHARSET_MAP = Collections.unmodifiableMap(mysqlToJavaMap); - TreeMap ucMap = new TreeMap(String.CASE_INSENSITIVE_ORDER); - Iterator javaNamesKeys = JAVA_TO_MYSQL_CHARSET_MAP.keySet().iterator(); - + TreeMap> ucMap = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + Iterator javaNamesKeys = JAVA_TO_MYSQL_CHARSET_MAP.keySet().iterator(); while (javaNamesKeys.hasNext()) { - String key = (String) javaNamesKeys.next(); - - ucMap.put(key.toUpperCase(Locale.ENGLISH), - JAVA_TO_MYSQL_CHARSET_MAP.get(key)); + String key = javaNamesKeys.next(); + ucMap.put(key.toUpperCase(Locale.ENGLISH), JAVA_TO_MYSQL_CHARSET_MAP.get(key)); } - JAVA_UC_TO_MYSQL_CHARSET_MAP = Collections.unmodifiableMap(ucMap); // // Character sets that we can't convert // ourselves. // - HashMap tempMapMulti = new HashMap(); + HashMap tempMapMulti = new HashMap(); CHARSET_CONFIG.setProperty("multibyteCharsets", // @@ -278,410 +364,296 @@ + "GB2312 = gb2312," + "UTF-8 = utf8," + "utf8 = utf8," - + "UnicodeBig = ucs2"); + + "UnicodeBig = ucs2," + + "UTF-16 = >5.2.0 utf16," + + "UTF-16LE = >5.6.0 utf16le," + + "UTF-32 = >5.2.0 utf32"); - populateMapWithKeyValuePairs("multibyteCharsets", tempMapMulti, false, - true); + populateMapWithKeyValuePairsUnversioned("multibyteCharsets", tempMapMulti, true); MULTIBYTE_CHARSETS = Collections.unmodifiableMap(tempMapMulti); - INDEX_TO_CHARSET = new String[211]; + Collation[] collation = new Collation[MAP_SIZE]; + collation[1] = new Collation(1, "big5_chinese_ci", MYSQL_CHARSET_NAME_big5); + collation[2] = new Collation(2, "latin2_czech_cs", MYSQL_CHARSET_NAME_latin2); + collation[3] = new Collation(3, "dec8_swedish_ci", MYSQL_CHARSET_NAME_dec8, "ISO8859_1"); // punting for "dec8" + collation[4] = new Collation(4, "cp850_general_ci", MYSQL_CHARSET_NAME_cp850, "ISO8859_1"); // punting for "dos" + collation[5] = new Collation(5, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1); + collation[6] = new Collation(6, "hp8_english_ci", MYSQL_CHARSET_NAME_hp8, "ISO8859_1"); // punting for "hp8" + collation[7] = new Collation(7, "koi8r_general_ci", MYSQL_CHARSET_NAME_koi8r); + collation[8] = new Collation(8, "latin1_swedish_ci", MYSQL_CHARSET_NAME_latin1 );//"Cp1252" + collation[9] = new Collation(9, "latin2_general_ci", MYSQL_CHARSET_NAME_latin2); + collation[10] = new Collation(10, "swe7_swedish_ci", MYSQL_CHARSET_NAME_swe7, "ISO8859_1"); // punting for "swe7" + collation[11] = new Collation(11, "ascii_general_ci", MYSQL_CHARSET_NAME_ascii); + collation[12] = new Collation(12, "ujis_japanese_ci", MYSQL_CHARSET_NAME_ujis); + collation[13] = new Collation(13, "sjis_japanese_ci", MYSQL_CHARSET_NAME_sjis); + collation[14] = new Collation(14, "cp1251_bulgarian_ci", MYSQL_CHARSET_NAME_cp1251); + collation[15] = new Collation(15, "latin1_danish_ci", MYSQL_CHARSET_NAME_latin1); + collation[16] = new Collation(16, "hebrew_general_ci", MYSQL_CHARSET_NAME_hebrew); + collation[17] = new Collation(17, "latin1_german1_ci", MYSQL_4_0_CHARSET_NAME_win1251); // removed since 4.1 + collation[18] = new Collation(18, "tis620_thai_ci", MYSQL_CHARSET_NAME_tis620); + collation[19] = new Collation(19, "euckr_korean_ci", MYSQL_CHARSET_NAME_euckr); + collation[20] = new Collation(20, "latin7_estonian_cs", MYSQL_CHARSET_NAME_latin7, "ISO8859_13"); // punting for "estonia"; + collation[21] = new Collation(21, "latin2_hungarian_ci", MYSQL_CHARSET_NAME_latin2); + collation[22] = new Collation(22, "koi8u_general_ci", MYSQL_CHARSET_NAME_koi8u, "KOI8_R"); // punting for "koi8_ukr" + collation[23] = new Collation(23, "cp1251_ukrainian_ci", MYSQL_CHARSET_NAME_cp1251); + collation[24] = new Collation(24, "gb2312_chinese_ci", MYSQL_CHARSET_NAME_gb2312); + collation[25] = new Collation(25, "greek_general_ci", MYSQL_CHARSET_NAME_greek); + collation[26] = new Collation(26, "cp1250_general_ci", MYSQL_CHARSET_NAME_cp1250); + collation[27] = new Collation(27, "latin2_croatian_ci", MYSQL_CHARSET_NAME_latin2); + collation[28] = new Collation(28, "gbk_chinese_ci", MYSQL_CHARSET_NAME_gbk); + collation[29] = new Collation(29, "cp1257_lithuanian_ci", MYSQL_CHARSET_NAME_cp1257); + collation[30] = new Collation(30, "latin5_turkish_ci", MYSQL_CHARSET_NAME_latin5); + collation[31] = new Collation(31, "latin1_german2_ci", MYSQL_CHARSET_NAME_latin1); + collation[32] = new Collation(32, "armscii8_general_ci", MYSQL_CHARSET_NAME_armscii8,"ISO8859_1"); + collation[33] = new Collation(33, "utf8_general_ci", MYSQL_CHARSET_NAME_utf8); + collation[34] = new Collation(34, "cp1250_czech_cs", MYSQL_CHARSET_NAME_cp1250); + collation[35] = new Collation(35, "ucs2_general_ci", MYSQL_CHARSET_NAME_ucs2); + collation[36] = new Collation(36, "cp866_general_ci", MYSQL_CHARSET_NAME_cp866); + collation[37] = new Collation(37, "keybcs2_general_ci", MYSQL_CHARSET_NAME_keybcs2, "Cp895"); + collation[38] = new Collation(38, "macce_general_ci", MYSQL_CHARSET_NAME_macce); + collation[39] = new Collation(39, "macroman_general_ci", MYSQL_CHARSET_NAME_macroman); + collation[40] = new Collation(40, "cp852_general_ci", MYSQL_CHARSET_NAME_cp852, "LATIN2"); // punting for "pclatin2" + collation[41] = new Collation(41, "latin7_general_ci", MYSQL_CHARSET_NAME_latin7, "ISO8859_13"); // punting for "latvian"; + collation[42] = new Collation(42, "latin7_general_cs", MYSQL_CHARSET_NAME_latin7, "ISO8859_13"); // punting for "latvian1"; + collation[43] = new Collation(43, "macce_bin", MYSQL_CHARSET_NAME_macce); + collation[44] = new Collation(44, "cp1250_croatian_ci", MYSQL_CHARSET_NAME_cp1250); + collation[45] = new Collation(45, "utf8mb4_general_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[46] = new Collation(46, "utf8mb4_bin", MYSQL_CHARSET_NAME_utf8mb4); + collation[47] = new Collation(47, "latin1_bin", MYSQL_CHARSET_NAME_latin1); + collation[48] = new Collation(48, "latin1_general_ci", MYSQL_CHARSET_NAME_latin1); + collation[49] = new Collation(49, "latin1_general_cs", MYSQL_CHARSET_NAME_latin1); + collation[50] = new Collation(50, "cp1251_bin", MYSQL_CHARSET_NAME_cp1251); + collation[51] = new Collation(51, "cp1251_general_ci", MYSQL_CHARSET_NAME_cp1251); + collation[52] = new Collation(52, "cp1251_general_cs", MYSQL_CHARSET_NAME_cp1251); + collation[53] = new Collation(53, "macroman_bin", MYSQL_CHARSET_NAME_macroman); + collation[54] = new Collation(54, "utf16_general_ci", MYSQL_CHARSET_NAME_utf16); + collation[55] = new Collation(55, "utf16_bin", MYSQL_CHARSET_NAME_utf16); + collation[56] = new Collation(56, "utf16le_general_ci", MYSQL_CHARSET_NAME_utf16le); + collation[57] = new Collation(57, "cp1256_general_ci", MYSQL_CHARSET_NAME_cp1256); + collation[58] = new Collation(58, "cp1257_bin", MYSQL_CHARSET_NAME_cp1257); + collation[59] = new Collation(59, "cp1257_general_ci", MYSQL_CHARSET_NAME_cp1257); + collation[60] = new Collation(60, "utf32_general_ci", MYSQL_CHARSET_NAME_utf32); + collation[61] = new Collation(61, "utf32_bin", MYSQL_CHARSET_NAME_utf32); + collation[62] = new Collation(62, "utf16le_bin", MYSQL_CHARSET_NAME_utf16le); + collation[63] = new Collation(63, "binary", MYSQL_CHARSET_NAME_binary); + collation[64] = new Collation(64, "armscii8_bin", MYSQL_CHARSET_NAME_armscii8,"ISO8859_2"); // punting "armscii" + collation[65] = new Collation(65, "ascii_bin", MYSQL_CHARSET_NAME_ascii); + collation[66] = new Collation(66, "cp1250_bin", MYSQL_CHARSET_NAME_cp1250); + collation[67] = new Collation(67, "cp1256_bin", MYSQL_CHARSET_NAME_cp1256); + collation[68] = new Collation(68, "cp866_bin", MYSQL_CHARSET_NAME_cp866); + collation[69] = new Collation(69, "dec8_bin", MYSQL_CHARSET_NAME_dec8, "US-ASCII"); // punting for "dec8" + collation[70] = new Collation(70, "greek_bin", MYSQL_CHARSET_NAME_greek); + collation[71] = new Collation(71, "hebrew_bin", MYSQL_CHARSET_NAME_hebrew); + collation[72] = new Collation(72, "hp8_bin", MYSQL_CHARSET_NAME_hp8, "US-ASCII"); // punting for "hp8" + collation[73] = new Collation(73, "keybcs2_bin", MYSQL_CHARSET_NAME_keybcs2, "Cp895"); // punting for "keybcs2" + collation[74] = new Collation(74, "koi8r_bin", MYSQL_CHARSET_NAME_koi8r); + collation[75] = new Collation(75, "koi8u_bin", MYSQL_CHARSET_NAME_koi8u, "KOI8_R"); // punting for koi8ukr" + collation[76] = new Collation(76, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[77] = new Collation(77, "latin2_bin", MYSQL_CHARSET_NAME_latin2); + collation[78] = new Collation(78, "latin5_bin", MYSQL_CHARSET_NAME_latin5); + collation[79] = new Collation(79, "latin7_bin", MYSQL_CHARSET_NAME_latin7); + collation[80] = new Collation(80, "cp850_bin", MYSQL_CHARSET_NAME_cp850); + collation[81] = new Collation(81, "cp852_bin", MYSQL_CHARSET_NAME_cp852); + collation[82] = new Collation(82, "swe7_bin", MYSQL_CHARSET_NAME_swe7, "ISO8859_1"); //"ISO8859_1"; // punting for "swe7" + collation[83] = new Collation(83, "utf8_bin", MYSQL_CHARSET_NAME_utf8); + collation[84] = new Collation(84, "big5_bin", MYSQL_CHARSET_NAME_big5); + collation[85] = new Collation(85, "euckr_bin", MYSQL_CHARSET_NAME_euckr); + collation[86] = new Collation(86, "gb2312_bin", MYSQL_CHARSET_NAME_gb2312); + collation[87] = new Collation(87, "gbk_bin", MYSQL_CHARSET_NAME_gbk); + collation[88] = new Collation(88, "sjis_bin", MYSQL_CHARSET_NAME_sjis); + collation[89] = new Collation(89, "tis620_bin", MYSQL_CHARSET_NAME_tis620); + collation[90] = new Collation(90, "ucs2_bin", MYSQL_CHARSET_NAME_ucs2); + collation[91] = new Collation(91, "ujis_bin", MYSQL_CHARSET_NAME_ujis); + collation[92] = new Collation(92, "geostd8_general_ci", MYSQL_CHARSET_NAME_geostd8, "US-ASCII"); //"US-ASCII"; //punting for "geostd8" + collation[93] = new Collation(93, "geostd8_bin", MYSQL_CHARSET_NAME_geostd8, "US-ASCII"); //"US-ASCII"; // punting for "geostd8" + collation[94] = new Collation(94, "latin1_spanish_ci", MYSQL_CHARSET_NAME_latin1); + collation[95] = new Collation(95, "cp932_japanese_ci", MYSQL_CHARSET_NAME_cp932); + collation[96] = new Collation(96, "cp932_bin", MYSQL_CHARSET_NAME_cp932); + collation[97] = new Collation(97, "eucjpms_japanese_ci", MYSQL_CHARSET_NAME_eucjpms); + collation[98] = new Collation(98, "eucjpms_bin", MYSQL_CHARSET_NAME_eucjpms); + collation[99] = new Collation(99, "cp1250_polish_ci", MYSQL_CHARSET_NAME_cp1250); + collation[100] = new Collation(100, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[101] = new Collation(101, "utf16_unicode_ci", MYSQL_CHARSET_NAME_utf16); + collation[102] = new Collation(102, "utf16_icelandic_ci", MYSQL_CHARSET_NAME_utf16); + collation[103] = new Collation(103, "utf16_latvian_ci", MYSQL_CHARSET_NAME_utf16); + collation[104] = new Collation(104, "utf16_romanian_ci", MYSQL_CHARSET_NAME_utf16); + collation[105] = new Collation(105, "utf16_slovenian_ci", MYSQL_CHARSET_NAME_utf16); + collation[106] = new Collation(106, "utf16_polish_ci", MYSQL_CHARSET_NAME_utf16); + collation[107] = new Collation(107, "utf16_estonian_ci", MYSQL_CHARSET_NAME_utf16); + collation[108] = new Collation(108, "utf16_spanish_ci", MYSQL_CHARSET_NAME_utf16); + collation[109] = new Collation(109, "utf16_swedish_ci", MYSQL_CHARSET_NAME_utf16); + collation[110] = new Collation(110, "utf16_turkish_ci", MYSQL_CHARSET_NAME_utf16); + collation[111] = new Collation(111, "utf16_czech_ci", MYSQL_CHARSET_NAME_utf16); + collation[112] = new Collation(112, "utf16_danish_ci", MYSQL_CHARSET_NAME_utf16); + collation[113] = new Collation(113, "utf16_lithuanian_ci", MYSQL_CHARSET_NAME_utf16); + collation[114] = new Collation(114, "utf16_slovak_ci", MYSQL_CHARSET_NAME_utf16); + collation[115] = new Collation(115, "utf16_spanish2_ci", MYSQL_CHARSET_NAME_utf16); + collation[116] = new Collation(116, "utf16_roman_ci", MYSQL_CHARSET_NAME_utf16); + collation[117] = new Collation(117, "utf16_persian_ci", MYSQL_CHARSET_NAME_utf16); + collation[118] = new Collation(118, "utf16_esperanto_ci", MYSQL_CHARSET_NAME_utf16); + collation[119] = new Collation(119, "utf16_hungarian_ci", MYSQL_CHARSET_NAME_utf16); + collation[120] = new Collation(120, "utf16_sinhala_ci", MYSQL_CHARSET_NAME_utf16); + collation[121] = new Collation(121, "utf16_german2_ci", MYSQL_CHARSET_NAME_utf16); + collation[122] = new Collation(122, "utf16_croatian_ci", MYSQL_CHARSET_NAME_utf16); + collation[123] = new Collation(123, "utf16_unicode_520_ci", MYSQL_CHARSET_NAME_utf16); + collation[124] = new Collation(124, "utf16_vietnamese_ci", MYSQL_CHARSET_NAME_utf16); + collation[125] = new Collation(125, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[126] = new Collation(126, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[127] = new Collation(127, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[128] = new Collation(128, "ucs2_unicode_ci", MYSQL_CHARSET_NAME_ucs2); + collation[129] = new Collation(129, "ucs2_icelandic_ci", MYSQL_CHARSET_NAME_ucs2); + collation[130] = new Collation(130, "ucs2_latvian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[131] = new Collation(131, "ucs2_romanian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[132] = new Collation(132, "ucs2_slovenian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[133] = new Collation(133, "ucs2_polish_ci", MYSQL_CHARSET_NAME_ucs2); + collation[134] = new Collation(134, "ucs2_estonian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[135] = new Collation(135, "ucs2_spanish_ci", MYSQL_CHARSET_NAME_ucs2); + collation[136] = new Collation(136, "ucs2_swedish_ci", MYSQL_CHARSET_NAME_ucs2); + collation[137] = new Collation(137, "ucs2_turkish_ci", MYSQL_CHARSET_NAME_ucs2); + collation[138] = new Collation(138, "ucs2_czech_ci", MYSQL_CHARSET_NAME_ucs2); + collation[139] = new Collation(139, "ucs2_danish_ci", MYSQL_CHARSET_NAME_ucs2); + collation[140] = new Collation(140, "ucs2_lithuanian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[141] = new Collation(141, "ucs2_slovak_ci", MYSQL_CHARSET_NAME_ucs2); + collation[142] = new Collation(142, "ucs2_spanish2_ci", MYSQL_CHARSET_NAME_ucs2); + collation[143] = new Collation(143, "ucs2_roman_ci", MYSQL_CHARSET_NAME_ucs2); + collation[144] = new Collation(144, "ucs2_persian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[145] = new Collation(145, "ucs2_esperanto_ci", MYSQL_CHARSET_NAME_ucs2); + collation[146] = new Collation(146, "ucs2_hungarian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[147] = new Collation(147, "ucs2_sinhala_ci", MYSQL_CHARSET_NAME_ucs2); + collation[148] = new Collation(148, "ucs2_german2_ci", MYSQL_CHARSET_NAME_ucs2); + collation[149] = new Collation(149, "ucs2_croatian_ci", MYSQL_CHARSET_NAME_ucs2); + collation[150] = new Collation(150, "ucs2_unicode_520_ci", MYSQL_CHARSET_NAME_ucs2); + collation[151] = new Collation(151, "ucs2_vietnamese_ci", MYSQL_CHARSET_NAME_ucs2); + collation[152] = new Collation(152, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[153] = new Collation(153, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[154] = new Collation(154, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[155] = new Collation(155, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[156] = new Collation(156, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[157] = new Collation(157, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[158] = new Collation(158, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[159] = new Collation(159, "ucs2_general_mysql500_ci", MYSQL_CHARSET_NAME_ucs2); + collation[160] = new Collation(160, "utf32_unicode_ci", MYSQL_CHARSET_NAME_utf32); + collation[161] = new Collation(161, "utf32_icelandic_ci", MYSQL_CHARSET_NAME_utf32); + collation[162] = new Collation(162, "utf32_latvian_ci", MYSQL_CHARSET_NAME_utf32); + collation[163] = new Collation(163, "utf32_romanian_ci", MYSQL_CHARSET_NAME_utf32); + collation[164] = new Collation(164, "utf32_slovenian_ci", MYSQL_CHARSET_NAME_utf32); + collation[165] = new Collation(165, "utf32_polish_ci", MYSQL_CHARSET_NAME_utf32); + collation[166] = new Collation(166, "utf32_estonian_ci", MYSQL_CHARSET_NAME_utf32); + collation[167] = new Collation(167, "utf32_spanish_ci", MYSQL_CHARSET_NAME_utf32); + collation[168] = new Collation(168, "utf32_swedish_ci", MYSQL_CHARSET_NAME_utf32); + collation[169] = new Collation(169, "utf32_turkish_ci", MYSQL_CHARSET_NAME_utf32); + collation[170] = new Collation(170, "utf32_czech_ci", MYSQL_CHARSET_NAME_utf32); + collation[171] = new Collation(171, "utf32_danish_ci", MYSQL_CHARSET_NAME_utf32); + collation[172] = new Collation(172, "utf32_lithuanian_ci", MYSQL_CHARSET_NAME_utf32); + collation[173] = new Collation(173, "utf32_slovak_ci", MYSQL_CHARSET_NAME_utf32); + collation[174] = new Collation(174, "utf32_spanish2_ci", MYSQL_CHARSET_NAME_utf32); + collation[175] = new Collation(175, "utf32_roman_ci", MYSQL_CHARSET_NAME_utf32); + collation[176] = new Collation(176, "utf32_persian_ci", MYSQL_CHARSET_NAME_utf32); + collation[177] = new Collation(177, "utf32_esperanto_ci", MYSQL_CHARSET_NAME_utf32); + collation[178] = new Collation(178, "utf32_hungarian_ci", MYSQL_CHARSET_NAME_utf32); + collation[179] = new Collation(179, "utf32_sinhala_ci", MYSQL_CHARSET_NAME_utf32); + collation[180] = new Collation(180, "utf32_german2_ci", MYSQL_CHARSET_NAME_utf32); + collation[181] = new Collation(181, "utf32_croatian_ci", MYSQL_CHARSET_NAME_utf32); + collation[182] = new Collation(182, "utf32_unicode_520_ci", MYSQL_CHARSET_NAME_utf32); + collation[183] = new Collation(183, "utf32_vietnamese_ci", MYSQL_CHARSET_NAME_utf32); + collation[184] = new Collation(184, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[185] = new Collation(185, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[186] = new Collation(186, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[187] = new Collation(187, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[188] = new Collation(188, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[189] = new Collation(189, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[190] = new Collation(190, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[191] = new Collation(191, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[192] = new Collation(192, "utf8_unicode_ci", MYSQL_CHARSET_NAME_utf8); + collation[193] = new Collation(193, "utf8_icelandic_ci", MYSQL_CHARSET_NAME_utf8); + collation[194] = new Collation(194, "utf8_latvian_ci", MYSQL_CHARSET_NAME_utf8); + collation[195] = new Collation(195, "utf8_romanian_ci", MYSQL_CHARSET_NAME_utf8); + collation[196] = new Collation(196, "utf8_slovenian_ci", MYSQL_CHARSET_NAME_utf8); + collation[197] = new Collation(197, "utf8_polish_ci", MYSQL_CHARSET_NAME_utf8); + collation[198] = new Collation(198, "utf8_estonian_ci", MYSQL_CHARSET_NAME_utf8); + collation[199] = new Collation(199, "utf8_spanish_ci", MYSQL_CHARSET_NAME_utf8); + collation[200] = new Collation(200, "utf8_swedish_ci", MYSQL_CHARSET_NAME_utf8); + collation[201] = new Collation(201, "utf8_turkish_ci", MYSQL_CHARSET_NAME_utf8); + collation[202] = new Collation(202, "utf8_czech_ci", MYSQL_CHARSET_NAME_utf8); + collation[203] = new Collation(203, "utf8_danish_ci", MYSQL_CHARSET_NAME_utf8); + collation[204] = new Collation(204, "utf8_lithuanian_ci", MYSQL_CHARSET_NAME_utf8); + collation[205] = new Collation(205, "utf8_slovak_ci", MYSQL_CHARSET_NAME_utf8); + collation[206] = new Collation(206, "utf8_spanish2_ci", MYSQL_CHARSET_NAME_utf8); + collation[207] = new Collation(207, "utf8_roman_ci", MYSQL_CHARSET_NAME_utf8); + collation[208] = new Collation(208, "utf8_persian_ci", MYSQL_CHARSET_NAME_utf8); + collation[209] = new Collation(209, "utf8_esperanto_ci", MYSQL_CHARSET_NAME_utf8); + collation[210] = new Collation(210, "utf8_hungarian_ci", MYSQL_CHARSET_NAME_utf8); + collation[211] = new Collation(211, "utf8_sinhala_ci", MYSQL_CHARSET_NAME_utf8); + collation[212] = new Collation(212, "utf8_german2_ci", MYSQL_CHARSET_NAME_utf8); + collation[213] = new Collation(213, "utf8_croatian_ci", MYSQL_CHARSET_NAME_utf8); + collation[214] = new Collation(214, "utf8_unicode_520_ci", MYSQL_CHARSET_NAME_utf8); + collation[215] = new Collation(215, "utf8_vietnamese_ci", MYSQL_CHARSET_NAME_utf8); + collation[216] = new Collation(216, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[217] = new Collation(217, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[218] = new Collation(218, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[219] = new Collation(219, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[220] = new Collation(220, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[221] = new Collation(221, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[222] = new Collation(222, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[223] = new Collation(223, "utf8_general_mysql500_ci", MYSQL_CHARSET_NAME_utf8); + collation[224] = new Collation(224, "utf8mb4_unicode_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[225] = new Collation(225, "utf8mb4_icelandic_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[226] = new Collation(226, "utf8mb4_latvian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[227] = new Collation(227, "utf8mb4_romanian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[228] = new Collation(228, "utf8mb4_slovenian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[229] = new Collation(229, "utf8mb4_polish_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[230] = new Collation(230, "utf8mb4_estonian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[231] = new Collation(231, "utf8mb4_spanish_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[232] = new Collation(232, "utf8mb4_swedish_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[233] = new Collation(233, "utf8mb4_turkish_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[234] = new Collation(234, "utf8mb4_czech_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[235] = new Collation(235, "utf8mb4_danish_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[236] = new Collation(236, "utf8mb4_lithuanian_ci",MYSQL_CHARSET_NAME_utf8mb4); + collation[237] = new Collation(237, "utf8mb4_slovak_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[238] = new Collation(238, "utf8mb4_spanish2_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[239] = new Collation(239, "utf8mb4_roman_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[240] = new Collation(240, "utf8mb4_persian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[241] = new Collation(241, "utf8mb4_esperanto_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[242] = new Collation(242, "utf8mb4_hungarian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[243] = new Collation(243, "utf8mb4_sinhala_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[244] = new Collation(244, "utf8mb4_german2_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[245] = new Collation(245, "utf8mb4_croatian_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[246] = new Collation(246, "utf8mb4_unicode_520_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[247] = new Collation(247, "utf8mb4_vietnamese_ci", MYSQL_CHARSET_NAME_utf8mb4); + collation[248] = new Collation(248, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[249] = new Collation(249, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[250] = new Collation(250, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[251] = new Collation(251, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[252] = new Collation(252, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[253] = new Collation(253, "latin1_german1_ci", MYSQL_CHARSET_NAME_latin1, NOT_USED); + collation[254] = new Collation(254, "utf8mb3_general_cs", MYSQL_CHARSET_NAME_utf8); + + INDEX_TO_COLLATION = new String[MAP_SIZE]; + INDEX_TO_CHARSET = new String[MAP_SIZE]; + Map indexToMysqlCharset = new HashMap(); + Map indexMap = new TreeMap(String.CASE_INSENSITIVE_ORDER); - try { - INDEX_TO_CHARSET[1] = getJavaEncodingForMysqlEncoding("big5", null); - INDEX_TO_CHARSET[2] = getJavaEncodingForMysqlEncoding("czech", null); - INDEX_TO_CHARSET[3] = "ISO8859_1"; // punting for "dec8" - INDEX_TO_CHARSET[4] = "ISO8859_1"; // punting for "dos" - INDEX_TO_CHARSET[5] = getJavaEncodingForMysqlEncoding("german1", - null); - INDEX_TO_CHARSET[6] = "ISO8859_1"; // punting for "hp8" - INDEX_TO_CHARSET[7] = getJavaEncodingForMysqlEncoding("koi8_ru", - null); - INDEX_TO_CHARSET[8] = getJavaEncodingForMysqlEncoding("latin1", - null); - INDEX_TO_CHARSET[9] = getJavaEncodingForMysqlEncoding("latin2", - null); - INDEX_TO_CHARSET[10] = "ISO8859_1"; // punting for "swe7" - INDEX_TO_CHARSET[11] = getJavaEncodingForMysqlEncoding("usa7", null); - INDEX_TO_CHARSET[12] = getJavaEncodingForMysqlEncoding("ujis", null); - INDEX_TO_CHARSET[13] = getJavaEncodingForMysqlEncoding("sjis", null); - INDEX_TO_CHARSET[14] = getJavaEncodingForMysqlEncoding("cp1251", - null); - INDEX_TO_CHARSET[15] = getJavaEncodingForMysqlEncoding("danish", - null); - INDEX_TO_CHARSET[16] = getJavaEncodingForMysqlEncoding("hebrew", - null); + for (int i = 1; i < MAP_SIZE; i++) { + INDEX_TO_COLLATION[i] = collation[i].collationName; + indexToMysqlCharset.put(i, collation[i].charsetName); + INDEX_TO_CHARSET[i] = collation[i].javaCharsetName; - INDEX_TO_CHARSET[17] = NOT_USED; // not used in the server - - INDEX_TO_CHARSET[18] = getJavaEncodingForMysqlEncoding("tis620", - null); - INDEX_TO_CHARSET[19] = getJavaEncodingForMysqlEncoding("euc_kr", - null); - INDEX_TO_CHARSET[20] = getJavaEncodingForMysqlEncoding("estonia", - null); - INDEX_TO_CHARSET[21] = getJavaEncodingForMysqlEncoding("hungarian", - null); - INDEX_TO_CHARSET[22] = "KOI8_R"; //punting for "koi8_ukr" - INDEX_TO_CHARSET[23] = getJavaEncodingForMysqlEncoding( - "win1251ukr", null); - INDEX_TO_CHARSET[24] = getJavaEncodingForMysqlEncoding("gb2312", - null); - INDEX_TO_CHARSET[25] = getJavaEncodingForMysqlEncoding("greek", - null); - INDEX_TO_CHARSET[26] = getJavaEncodingForMysqlEncoding("win1250", - null); - INDEX_TO_CHARSET[27] = getJavaEncodingForMysqlEncoding("croat", - null); - INDEX_TO_CHARSET[28] = getJavaEncodingForMysqlEncoding("gbk", null); - INDEX_TO_CHARSET[29] = getJavaEncodingForMysqlEncoding("cp1257", - null); - INDEX_TO_CHARSET[30] = getJavaEncodingForMysqlEncoding("latin5", - null); - INDEX_TO_CHARSET[31] = getJavaEncodingForMysqlEncoding("latin1_de", - null); - INDEX_TO_CHARSET[32] = "ISO8859_1"; // punting "armscii8" - INDEX_TO_CHARSET[33] = getJavaEncodingForMysqlEncoding("utf8", null); - INDEX_TO_CHARSET[34] = "Cp1250"; // punting "win1250ch" - INDEX_TO_CHARSET[35] = getJavaEncodingForMysqlEncoding("ucs2", null); - INDEX_TO_CHARSET[36] = getJavaEncodingForMysqlEncoding("cp866", - null); - INDEX_TO_CHARSET[37] = "Cp895"; // punting "keybcs2" - INDEX_TO_CHARSET[38] = getJavaEncodingForMysqlEncoding("macce", - null); - INDEX_TO_CHARSET[39] = getJavaEncodingForMysqlEncoding("macroman", - null); - INDEX_TO_CHARSET[40] = "latin2"; // punting "pclatin2" - INDEX_TO_CHARSET[41] = getJavaEncodingForMysqlEncoding("latvian", - null); - INDEX_TO_CHARSET[42] = getJavaEncodingForMysqlEncoding("latvian1", - null); - INDEX_TO_CHARSET[43] = getJavaEncodingForMysqlEncoding("macce", - null); - INDEX_TO_CHARSET[44] = getJavaEncodingForMysqlEncoding("macce", - null); - INDEX_TO_CHARSET[45] = getJavaEncodingForMysqlEncoding("macce", - null); - INDEX_TO_CHARSET[46] = getJavaEncodingForMysqlEncoding("macce", - null); - INDEX_TO_CHARSET[47] = getJavaEncodingForMysqlEncoding("latin1", - null); - INDEX_TO_CHARSET[48] = getJavaEncodingForMysqlEncoding( - "latin1", null); - INDEX_TO_CHARSET[49] = getJavaEncodingForMysqlEncoding( - "latin1", null); - INDEX_TO_CHARSET[50] = getJavaEncodingForMysqlEncoding("cp1251", - null); - INDEX_TO_CHARSET[51] = getJavaEncodingForMysqlEncoding( - "cp1251", null); - INDEX_TO_CHARSET[52] = getJavaEncodingForMysqlEncoding( - "cp1251", null); - INDEX_TO_CHARSET[53] = getJavaEncodingForMysqlEncoding( - "macroman", null); - INDEX_TO_CHARSET[54] = getJavaEncodingForMysqlEncoding( - "macroman", null); - INDEX_TO_CHARSET[55] = getJavaEncodingForMysqlEncoding( - "macroman", null); - INDEX_TO_CHARSET[56] = getJavaEncodingForMysqlEncoding( - "macroman", null); - INDEX_TO_CHARSET[57] = getJavaEncodingForMysqlEncoding("cp1256", - null); - - INDEX_TO_CHARSET[58] = NOT_USED; // not used - INDEX_TO_CHARSET[59] = NOT_USED; // not used - INDEX_TO_CHARSET[60] = NOT_USED; // not used - INDEX_TO_CHARSET[61] = NOT_USED; // not used - INDEX_TO_CHARSET[62] = NOT_USED; // not used - - INDEX_TO_CHARSET[63] = getJavaEncodingForMysqlEncoding("binary", - null); - INDEX_TO_CHARSET[64] = "ISO8859_2"; // punting "armscii" - INDEX_TO_CHARSET[65] = getJavaEncodingForMysqlEncoding("ascii", - null); - INDEX_TO_CHARSET[66] = getJavaEncodingForMysqlEncoding("cp1250", - null); - INDEX_TO_CHARSET[67] = getJavaEncodingForMysqlEncoding("cp1256", - null); - INDEX_TO_CHARSET[68] = getJavaEncodingForMysqlEncoding("cp866", - null); - INDEX_TO_CHARSET[69] = "US-ASCII"; // punting for "dec8" - INDEX_TO_CHARSET[70] = getJavaEncodingForMysqlEncoding("greek", - null); - INDEX_TO_CHARSET[71] = getJavaEncodingForMysqlEncoding("hebrew", - null); - INDEX_TO_CHARSET[72] = "US-ASCII"; // punting for "hp8" - INDEX_TO_CHARSET[73] = "Cp895"; // punting for "keybcs2" - INDEX_TO_CHARSET[74] = getJavaEncodingForMysqlEncoding("koi8r", - null); - INDEX_TO_CHARSET[75] = "KOI8_r"; // punting for koi8ukr" - - INDEX_TO_CHARSET[76] = NOT_USED; // not used - - INDEX_TO_CHARSET[77] = getJavaEncodingForMysqlEncoding("latin2", - null); - INDEX_TO_CHARSET[78] = getJavaEncodingForMysqlEncoding("latin5", - null); - INDEX_TO_CHARSET[79] = getJavaEncodingForMysqlEncoding("latin7", - null); - INDEX_TO_CHARSET[80] = getJavaEncodingForMysqlEncoding("cp850", - null); - INDEX_TO_CHARSET[81] = getJavaEncodingForMysqlEncoding("cp852", - null); - INDEX_TO_CHARSET[82] = "ISO8859_1"; // punting for "swe7" - INDEX_TO_CHARSET[83] = getJavaEncodingForMysqlEncoding("utf8", null); - INDEX_TO_CHARSET[84] = getJavaEncodingForMysqlEncoding("big5", null); - INDEX_TO_CHARSET[85] = getJavaEncodingForMysqlEncoding("euckr", - null); - INDEX_TO_CHARSET[86] = getJavaEncodingForMysqlEncoding("gb2312", - null); - INDEX_TO_CHARSET[87] = getJavaEncodingForMysqlEncoding("gbk", null); - INDEX_TO_CHARSET[88] = getJavaEncodingForMysqlEncoding("sjis", null); - INDEX_TO_CHARSET[89] = getJavaEncodingForMysqlEncoding("tis620", - null); - INDEX_TO_CHARSET[90] = getJavaEncodingForMysqlEncoding("ucs2", null); - INDEX_TO_CHARSET[91] = getJavaEncodingForMysqlEncoding("ujis", null); - INDEX_TO_CHARSET[92] = "US-ASCII"; //punting for "geostd8" - INDEX_TO_CHARSET[93] = "US-ASCII"; // punting for "geostd8" - INDEX_TO_CHARSET[94] = getJavaEncodingForMysqlEncoding("latin1", - null); - INDEX_TO_CHARSET[95] = getJavaEncodingForMysqlEncoding("cp932", - null); - INDEX_TO_CHARSET[96] = getJavaEncodingForMysqlEncoding("cp932", - null); - INDEX_TO_CHARSET[97] = getJavaEncodingForMysqlEncoding("eucjpms", - null); - INDEX_TO_CHARSET[98] = getJavaEncodingForMysqlEncoding("eucjpms", - null); - - for (int i = 99; i < 128; i++) { - INDEX_TO_CHARSET[i] = NOT_USED; // not used - } - - INDEX_TO_CHARSET[128] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[129] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[130] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[131] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[132] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[133] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[134] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[135] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[136] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[137] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[138] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[139] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[140] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[141] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[142] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[143] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[144] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[145] = getJavaEncodingForMysqlEncoding("ucs2", - null); - INDEX_TO_CHARSET[146] = getJavaEncodingForMysqlEncoding("ucs2", - null); + if (INDEX_TO_CHARSET[i] != null) indexMap.put(INDEX_TO_CHARSET[i], i); + } - for (int i = 147; i < 192; i++) { - INDEX_TO_CHARSET[i] = NOT_USED; // not used - } - - INDEX_TO_CHARSET[192] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[193] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[194] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[195] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[196] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[197] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[198] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[199] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[200] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[201] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[202] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[203] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[204] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[205] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[206] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[207] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[208] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[209] = getJavaEncodingForMysqlEncoding("utf8", - null); - INDEX_TO_CHARSET[210] = getJavaEncodingForMysqlEncoding("utf8", - null); - - // Sanity check - - for (int i = 1; i < INDEX_TO_CHARSET.length; i++) { - if (INDEX_TO_CHARSET[i] == null) { - throw new RuntimeException("Assertion failure: No mapping from charset index " + i + " to a Java character set"); - } - } - } catch (SQLException sqlEx) { - // ignore, it won't happen in this case + // Sanity check + for (int i = 1; i < MAP_SIZE; i++) { + if (INDEX_TO_COLLATION[i] == null) throw new RuntimeException("Assertion failure: No mapping from charset index " + i + " to a mysql collation"); + if (indexToMysqlCharset.get(i) == null) throw new RuntimeException("Assertion failure: No mapping from charset index " + i + " to a mysql character set"); + if (INDEX_TO_CHARSET[i] == null) throw new RuntimeException("Assertion failure: No mapping from charset index " + i + " to a Java character set"); } + + MYSQL_ENCODING_NAME_TO_CHARSET_INDEX_MAP = Collections.unmodifiableMap(indexMap); + STATIC_INDEX_TO_MYSQL_CHARSET_MAP = Collections.unmodifiableMap(indexToMysqlCharset); - INDEX_TO_COLLATION = new String[211]; + Map tempMap = new HashMap(); - INDEX_TO_COLLATION[1] = "big5_chinese_ci"; - INDEX_TO_COLLATION[2] = "latin2_czech_cs"; - INDEX_TO_COLLATION[3] = "dec8_swedish_ci"; - INDEX_TO_COLLATION[4] = "cp850_general_ci"; - INDEX_TO_COLLATION[5] = "latin1_german1_ci"; - INDEX_TO_COLLATION[6] = "hp8_english_ci"; - INDEX_TO_COLLATION[7] = "koi8r_general_ci"; - INDEX_TO_COLLATION[8] = "latin1_swedish_ci"; - INDEX_TO_COLLATION[9] = "latin2_general_ci"; - INDEX_TO_COLLATION[10] = "swe7_swedish_ci"; - INDEX_TO_COLLATION[11] = "ascii_general_ci"; - INDEX_TO_COLLATION[12] = "ujis_japanese_ci"; - INDEX_TO_COLLATION[13] = "sjis_japanese_ci"; - INDEX_TO_COLLATION[14] = "cp1251_bulgarian_ci"; - INDEX_TO_COLLATION[15] = "latin1_danish_ci"; - INDEX_TO_COLLATION[16] = "hebrew_general_ci"; - INDEX_TO_COLLATION[18] = "tis620_thai_ci"; - INDEX_TO_COLLATION[19] = "euckr_korean_ci"; - INDEX_TO_COLLATION[20] = "latin7_estonian_cs"; - INDEX_TO_COLLATION[21] = "latin2_hungarian_ci"; - INDEX_TO_COLLATION[22] = "koi8u_general_ci"; - INDEX_TO_COLLATION[23] = "cp1251_ukrainian_ci"; - INDEX_TO_COLLATION[24] = "gb2312_chinese_ci"; - INDEX_TO_COLLATION[25] = "greek_general_ci"; - INDEX_TO_COLLATION[26] = "cp1250_general_ci"; - INDEX_TO_COLLATION[27] = "latin2_croatian_ci"; - INDEX_TO_COLLATION[28] = "gbk_chinese_ci"; - INDEX_TO_COLLATION[29] = "cp1257_lithuanian_ci"; - INDEX_TO_COLLATION[30] = "latin5_turkish_ci"; - INDEX_TO_COLLATION[31] = "latin1_german2_ci"; - INDEX_TO_COLLATION[32] = "armscii8_general_ci"; - INDEX_TO_COLLATION[33] = "utf8_general_ci"; - INDEX_TO_COLLATION[34] = "cp1250_czech_cs"; - INDEX_TO_COLLATION[35] = "ucs2_general_ci"; - INDEX_TO_COLLATION[36] = "cp866_general_ci"; - INDEX_TO_COLLATION[37] = "keybcs2_general_ci"; - INDEX_TO_COLLATION[38] = "macce_general_ci"; - INDEX_TO_COLLATION[39] = "macroman_general_ci"; - INDEX_TO_COLLATION[40] = "cp852_general_ci"; - INDEX_TO_COLLATION[41] = "latin7_general_ci"; - INDEX_TO_COLLATION[42] = "latin7_general_cs"; - INDEX_TO_COLLATION[43] = "macce_bin"; - INDEX_TO_COLLATION[44] = "cp1250_croatian_ci"; - INDEX_TO_COLLATION[47] = "latin1_bin"; - INDEX_TO_COLLATION[48] = "latin1_general_ci"; - INDEX_TO_COLLATION[49] = "latin1_general_cs"; - INDEX_TO_COLLATION[50] = "cp1251_bin"; - INDEX_TO_COLLATION[51] = "cp1251_general_ci"; - INDEX_TO_COLLATION[52] = "cp1251_general_cs"; - INDEX_TO_COLLATION[53] = "macroman_bin"; - INDEX_TO_COLLATION[57] = "cp1256_general_ci"; - INDEX_TO_COLLATION[58] = "cp1257_bin"; - INDEX_TO_COLLATION[59] = "cp1257_general_ci"; - INDEX_TO_COLLATION[63] = "binary"; - INDEX_TO_COLLATION[64] = "armscii8_bin"; - INDEX_TO_COLLATION[65] = "ascii_bin"; - INDEX_TO_COLLATION[66] = "cp1250_bin"; - INDEX_TO_COLLATION[67] = "cp1256_bin"; - INDEX_TO_COLLATION[68] = "cp866_bin"; - INDEX_TO_COLLATION[69] = "dec8_bin"; - INDEX_TO_COLLATION[70] = "greek_bin"; - INDEX_TO_COLLATION[71] = "hebrew_bin"; - INDEX_TO_COLLATION[72] = "hp8_bin"; - INDEX_TO_COLLATION[73] = "keybcs2_bin"; - INDEX_TO_COLLATION[74] = "koi8r_bin"; - INDEX_TO_COLLATION[75] = "koi8u_bin"; - INDEX_TO_COLLATION[77] = "latin2_bin"; - INDEX_TO_COLLATION[78] = "latin5_bin"; - INDEX_TO_COLLATION[79] = "latin7_bin"; - INDEX_TO_COLLATION[80] = "cp850_bin"; - INDEX_TO_COLLATION[81] = "cp852_bin"; - INDEX_TO_COLLATION[82] = "swe7_bin"; - INDEX_TO_COLLATION[83] = "utf8_bin"; - INDEX_TO_COLLATION[84] = "big5_bin"; - INDEX_TO_COLLATION[85] = "euckr_bin"; - INDEX_TO_COLLATION[86] = "gb2312_bin"; - INDEX_TO_COLLATION[87] = "gbk_bin"; - INDEX_TO_COLLATION[88] = "sjis_bin"; - INDEX_TO_COLLATION[89] = "tis620_bin"; - INDEX_TO_COLLATION[90] = "ucs2_bin"; - INDEX_TO_COLLATION[91] = "ujis_bin"; - INDEX_TO_COLLATION[92] = "geostd8_general_ci"; - INDEX_TO_COLLATION[93] = "geostd8_bin"; - INDEX_TO_COLLATION[94] = "latin1_spanish_ci"; - INDEX_TO_COLLATION[95] = "cp932_japanese_ci"; - INDEX_TO_COLLATION[96] = "cp932_bin"; - INDEX_TO_COLLATION[97] = "eucjpms_japanese_ci"; - INDEX_TO_COLLATION[98] = "eucjpms_bin"; - INDEX_TO_COLLATION[99] = "cp1250_polish_ci"; - INDEX_TO_COLLATION[128] = "ucs2_unicode_ci"; - INDEX_TO_COLLATION[129] = "ucs2_icelandic_ci"; - INDEX_TO_COLLATION[130] = "ucs2_latvian_ci"; - INDEX_TO_COLLATION[131] = "ucs2_romanian_ci"; - INDEX_TO_COLLATION[132] = "ucs2_slovenian_ci"; - INDEX_TO_COLLATION[133] = "ucs2_polish_ci"; - INDEX_TO_COLLATION[134] = "ucs2_estonian_ci"; - INDEX_TO_COLLATION[135] = "ucs2_spanish_ci"; - INDEX_TO_COLLATION[136] = "ucs2_swedish_ci"; - INDEX_TO_COLLATION[137] = "ucs2_turkish_ci"; - INDEX_TO_COLLATION[138] = "ucs2_czech_ci"; - INDEX_TO_COLLATION[139] = "ucs2_danish_ci"; - INDEX_TO_COLLATION[140] = "ucs2_lithuanian_ci "; - INDEX_TO_COLLATION[141] = "ucs2_slovak_ci"; - INDEX_TO_COLLATION[142] = "ucs2_spanish2_ci"; - INDEX_TO_COLLATION[143] = "ucs2_roman_ci"; - INDEX_TO_COLLATION[144] = "ucs2_persian_ci"; - INDEX_TO_COLLATION[145] = "ucs2_esperanto_ci"; - INDEX_TO_COLLATION[146] = "ucs2_hungarian_ci"; - INDEX_TO_COLLATION[192] = "utf8_unicode_ci"; - INDEX_TO_COLLATION[193] = "utf8_icelandic_ci"; - INDEX_TO_COLLATION[194] = "utf8_latvian_ci"; - INDEX_TO_COLLATION[195] = "utf8_romanian_ci"; - INDEX_TO_COLLATION[196] = "utf8_slovenian_ci"; - INDEX_TO_COLLATION[197] = "utf8_polish_ci"; - INDEX_TO_COLLATION[198] = "utf8_estonian_ci"; - INDEX_TO_COLLATION[199] = "utf8_spanish_ci"; - INDEX_TO_COLLATION[200] = "utf8_swedish_ci"; - INDEX_TO_COLLATION[201] = "utf8_turkish_ci"; - INDEX_TO_COLLATION[202] = "utf8_czech_ci"; - INDEX_TO_COLLATION[203] = "utf8_danish_ci"; - INDEX_TO_COLLATION[204] = "utf8_lithuanian_ci "; - INDEX_TO_COLLATION[205] = "utf8_slovak_ci"; - INDEX_TO_COLLATION[206] = "utf8_spanish2_ci"; - INDEX_TO_COLLATION[207] = "utf8_roman_ci"; - INDEX_TO_COLLATION[208] = "utf8_persian_ci"; - INDEX_TO_COLLATION[209] = "utf8_esperanto_ci"; - INDEX_TO_COLLATION[210] = "utf8_hungarian_ci"; - - Map tempMap = new HashMap(); - tempMap.put("czech", "latin2"); tempMap.put("danish", "latin1"); tempMap.put("dutch", "latin1"); @@ -711,63 +683,59 @@ Collections.unmodifiableMap(tempMap); } - public final static String getJavaEncodingForMysqlEncoding(String mysqlEncoding, + public final static String getMysqlEncodingForJavaEncoding(String javaEncodingUC, Connection conn) throws SQLException { - if (conn != null && conn.versionMeetsMinimum(4, 1, 0) && - "latin1".equalsIgnoreCase(mysqlEncoding)) { - return "Cp1252"; - } - - return (String) MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlEncoding); - } + try { + List mysqlEncodings = CharsetMapping.JAVA_UC_TO_MYSQL_CHARSET_MAP.get(javaEncodingUC); - public final static String getMysqlEncodingForJavaEncoding(String javaEncodingUC, - Connection conn) throws SQLException { - List mysqlEncodings = (List) CharsetMapping.JAVA_UC_TO_MYSQL_CHARSET_MAP - .get(javaEncodingUC); - ; + if (mysqlEncodings != null) { + Iterator iter = mysqlEncodings.iterator(); - if (mysqlEncodings != null) { - Iterator iter = mysqlEncodings.iterator(); + VersionedStringProperty versionedProp = null; - VersionedStringProperty versionedProp = null; + while (iter.hasNext()) { + VersionedStringProperty propToCheck = iter.next(); - while (iter.hasNext()) { - VersionedStringProperty propToCheck = (VersionedStringProperty) iter - .next(); + if (conn == null) { + // Take the first one we get - if (conn == null) { - // Take the first one we get + return propToCheck.toString(); + } - return propToCheck.toString(); - } + if (versionedProp != null && !versionedProp.preferredValue) { + if (versionedProp.majorVersion == propToCheck.majorVersion + && versionedProp.minorVersion == propToCheck.minorVersion + && versionedProp.subminorVersion == propToCheck.subminorVersion) { + return versionedProp.toString(); + } + } - if (versionedProp != null && !versionedProp.preferredValue) { - if (versionedProp.majorVersion == propToCheck.majorVersion - && versionedProp.minorVersion == propToCheck.minorVersion - && versionedProp.subminorVersion == propToCheck.subminorVersion) { - return versionedProp.toString(); + if (propToCheck.isOkayForVersion(conn)) { + if (propToCheck.preferredValue) { + return propToCheck.toString(); + } + + versionedProp = propToCheck; + } else { + break; } } - if (propToCheck.isOkayForVersion(conn)) { - if (propToCheck.preferredValue) { - return propToCheck.toString(); - } - - versionedProp = propToCheck; - } else { - break; + if (versionedProp != null) { + return versionedProp.toString(); } } - if (versionedProp != null) { - return versionedProp.toString(); - } + return null; + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; } - return null; } final static int getNumberOfCharsetsConfigured() { @@ -786,7 +754,23 @@ * @return the Java encoding name that error messages use * @throws SQLException if determination of the character encoding fails */ - final static String getCharacterEncodingForErrorMessages(Connection conn) throws SQLException { + final static String getCharacterEncodingForErrorMessages(ConnectionImpl conn) throws SQLException { + + // As of MySQL 5.5, the server constructs error messages using UTF-8 + // and returns them to clients in the character set specified by the + // character_set_results system variable. + if (conn.versionMeetsMinimum(5, 5, 0)) { + String errorMessageEncodingMysql = conn.getServerVariable("character_set_results"); + if (errorMessageEncodingMysql != null) { + String javaEncoding = conn.getJavaEncodingForMysqlEncoding(errorMessageEncodingMysql); + if (javaEncoding != null) { + return javaEncoding; + } + } + + return "UTF-8"; + } + String errorMessageFile = conn.getServerVariable("language"); if (errorMessageFile == null || errorMessageFile.length() == 0) { @@ -817,14 +801,14 @@ errorMessageFile = errorMessageFile.substring(lastSlashIndex + 1, endWithoutSlash); - String errorMessageEncodingMysql = (String)ERROR_MESSAGE_FILE_TO_MYSQL_CHARSET_MAP.get(errorMessageFile); + String errorMessageEncodingMysql = ERROR_MESSAGE_FILE_TO_MYSQL_CHARSET_MAP.get(errorMessageFile); if (errorMessageEncodingMysql == null) { // punt return "Cp1252"; } - String javaEncoding = getJavaEncodingForMysqlEncoding(errorMessageEncodingMysql, conn); + String javaEncoding = conn.getJavaEncodingForMysqlEncoding(errorMessageEncodingMysql); if (javaEncoding == null) { // punt @@ -850,77 +834,80 @@ return MULTIBYTE_CHARSETS.containsKey(javaEncodingNameUC); } - private static void populateMapWithKeyValuePairs(String configKey, - Map mapToPopulate, boolean addVersionedProperties, - boolean addUppercaseKeys) { + private static void populateMapWithKeyValuePairsUnversioned(String configKey, Map mapToPopulate, boolean addUppercaseKeys) { String javaToMysqlConfig = CHARSET_CONFIG.getProperty(configKey); + if (javaToMysqlConfig == null) throw new RuntimeException("Could not find configuration value " + "\"" + configKey + "\" in Charsets.properties resource"); + + List mappings = StringUtils.split(javaToMysqlConfig, ",", true); + if (mappings == null) throw new RuntimeException("Missing/corrupt entry for \"" + configKey + "\" in Charsets.properties."); - if (javaToMysqlConfig != null) { - List mappings = StringUtils.split(javaToMysqlConfig, ",", true); + Iterator mappingsIter = mappings.iterator(); + while (mappingsIter.hasNext()) { + String aMapping = mappingsIter.next(); + List parsedPair = StringUtils.split(aMapping, "=", true); + if (parsedPair.size() != 2) throw new RuntimeException("Syntax error in Charsets.properties " + "resource for token \"" + aMapping + "\"."); - if (mappings != null) { - Iterator mappingsIter = mappings.iterator(); + String key = parsedPair.get(0).toString(); + String value = parsedPair.get(1).toString(); + mapToPopulate.put(key, value); - while (mappingsIter.hasNext()) { - String aMapping = (String) mappingsIter.next(); + if (addUppercaseKeys) mapToPopulate.put(key.toUpperCase(Locale.ENGLISH), value); + } + } - List parsedPair = StringUtils.split(aMapping, "=", true); + private static void populateMapWithKeyValuePairsVersioned(String configKey, Map> mapToPopulate, boolean addUppercaseKeys) { + String javaToMysqlConfig = CHARSET_CONFIG.getProperty(configKey); + if (javaToMysqlConfig == null) throw new RuntimeException("Could not find configuration value " + "\"" + configKey + "\" in Charsets.properties resource"); - if (parsedPair.size() == 2) { - String key = parsedPair.get(0).toString(); - String value = parsedPair.get(1).toString(); + List mappings = StringUtils.split(javaToMysqlConfig, ",", true); + if (mappings == null) throw new RuntimeException("Missing/corrupt entry for \"" + configKey + "\" in Charsets.properties."); - if (addVersionedProperties) { - List versionedProperties = (List) mapToPopulate - .get(key); + Iterator mappingsIter = mappings.iterator(); + while (mappingsIter.hasNext()) { + String aMapping = mappingsIter.next(); + List parsedPair = StringUtils.split(aMapping, "=", true); + if (parsedPair.size() != 2) throw new RuntimeException("Syntax error in Charsets.properties " + "resource for token \"" + aMapping + "\"."); - if (versionedProperties == null) { - versionedProperties = new ArrayList(); - mapToPopulate.put(key, versionedProperties); - } + String key = parsedPair.get(0).toString(); + String value = parsedPair.get(1).toString(); - VersionedStringProperty verProp = new VersionedStringProperty( - value); - versionedProperties.add(verProp); + List versionedProperties = mapToPopulate.get(key); - if (addUppercaseKeys) { - String keyUc = key.toUpperCase(Locale.ENGLISH); + if (versionedProperties == null) { + versionedProperties = new ArrayList(); + mapToPopulate.put(key, versionedProperties); + } - versionedProperties = (List) mapToPopulate - .get(keyUc); + VersionedStringProperty verProp = new VersionedStringProperty(value); + versionedProperties.add(verProp); - if (versionedProperties == null) { - versionedProperties = new ArrayList(); - mapToPopulate.put(keyUc, - versionedProperties); - } + if (addUppercaseKeys) { + String keyUc = key.toUpperCase(Locale.ENGLISH); + versionedProperties = mapToPopulate.get(keyUc); - versionedProperties.add(verProp); - } - } else { - mapToPopulate.put(key, value); - - if (addUppercaseKeys) { - mapToPopulate.put(key - .toUpperCase(Locale.ENGLISH), value); - } - } - } else { - throw new RuntimeException( - "Syntax error in Charsets.properties " - + "resource for token \"" + aMapping - + "\"."); - } + if (versionedProperties == null) { + versionedProperties = new ArrayList(); + mapToPopulate.put(keyUc, versionedProperties); } - } else { - throw new RuntimeException("Missing/corrupt entry for \"" - + configKey + "\" in Charsets.properties."); + + versionedProperties.add(verProp); } - } else { - throw new RuntimeException("Could not find configuration value " - + "\"" + configKey + "\" in Charsets.properties resource"); } } + + public static int getCharsetIndexForMysqlEncodingName(String name) { + if (name == null) { + return 0; + } + + Integer asInt = MYSQL_ENCODING_NAME_TO_CHARSET_INDEX_MAP.get(name); + + if (asInt == null) { + return 0; + } + + return asInt.intValue(); + } } class VersionedStringProperty { @@ -953,7 +940,7 @@ } String versionInfo = property.substring(0, charPos); - List versionParts = StringUtils.split(versionInfo, ".", true); + List versionParts = StringUtils.split(versionInfo, ".", true); majorVersion = Integer.parseInt(versionParts.get(0).toString()); @@ -989,7 +976,44 @@ subminorVersion); } + public String toString() { return propertyInfo; } } + +class Collation { + public int index; + public String collationName; + public String charsetName; + public String javaCharsetName; + + public Collation(int index, String collationName, String charsetName) { + this.index = index; + this.collationName = collationName; + this.charsetName = charsetName; + this.javaCharsetName = CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(charsetName); + } + + public Collation(int index, String collationName, String charsetName, String javaCharsetName) { + this.index = index; + this.collationName = collationName; + this.charsetName = charsetName; + this.javaCharsetName = javaCharsetName; + } + + public String toString() { + StringBuffer asString = new StringBuffer(); + asString.append("["); + asString.append("index="); + asString.append(this.index); + asString.append(",collationName="); + asString.append(this.collationName); + asString.append(",charsetName="); + asString.append(this.charsetName); + asString.append(",javaCharsetName="); + asString.append(this.javaCharsetName); + asString.append("]"); + return asString.toString(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Clob.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Clob.java (.../Clob.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Clob.java (.../Clob.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.ByteArrayInputStream; @@ -30,7 +29,6 @@ import java.io.Reader; import java.io.StringReader; import java.io.Writer; - import java.sql.SQLException; /** @@ -41,17 +39,24 @@ */ public class Clob implements java.sql.Clob, OutputStreamWatcher, WriterWatcher { private String charData; - - Clob(String charDataInit) { + private ExceptionInterceptor exceptionInterceptor; + + Clob(ExceptionInterceptor exceptionInterceptor) { + this.charData = ""; + this.exceptionInterceptor = exceptionInterceptor; + } + + Clob(String charDataInit, ExceptionInterceptor exceptionInterceptor) { this.charData = charDataInit; + this.exceptionInterceptor = exceptionInterceptor; } /** * @see java.sql.Clob#getAsciiStream() */ public InputStream getAsciiStream() throws SQLException { if (this.charData != null) { - return new ByteArrayInputStream(this.charData.getBytes()); + return new ByteArrayInputStream(StringUtils.getBytes(this.charData)); } return null; @@ -74,7 +79,7 @@ public String getSubString(long startPos, int length) throws SQLException { if (startPos < 1) { throw SQLError.createSQLException(Messages.getString("Clob.6"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } int adjustedStartPos = (int)startPos - 1; @@ -83,7 +88,7 @@ if (this.charData != null) { if (adjustedEndIndex > this.charData.length()) { throw SQLError.createSQLException(Messages.getString("Clob.7"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } return this.charData.substring(adjustedStartPos, @@ -119,13 +124,13 @@ if (startPos < 1) { throw SQLError.createSQLException( Messages.getString("Clob.8") //$NON-NLS-1$ - + startPos + Messages.getString("Clob.9"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + + startPos + Messages.getString("Clob.9"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$ } if (this.charData != null) { if ((startPos - 1) > this.charData.length()) { throw SQLError.createSQLException(Messages.getString("Clob.10"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } int pos = this.charData.indexOf(stringToFind, (int) (startPos - 1)); @@ -142,14 +147,14 @@ public OutputStream setAsciiStream(long indexToWriteAt) throws SQLException { if (indexToWriteAt < 1) { throw SQLError.createSQLException(Messages.getString("Clob.0"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } WatchableOutputStream bytesOut = new WatchableOutputStream(); bytesOut.setWatcher(this); if (indexToWriteAt > 0) { - bytesOut.write(this.charData.getBytes(), 0, + bytesOut.write(StringUtils.getBytes(this.charData), 0, (int) (indexToWriteAt - 1)); } @@ -162,7 +167,7 @@ public Writer setCharacterStream(long indexToWriteAt) throws SQLException { if (indexToWriteAt < 1) { throw SQLError.createSQLException(Messages.getString("Clob.1"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } WatchableWriter writer = new WatchableWriter(); @@ -184,12 +189,12 @@ public int setString(long pos, String str) throws SQLException { if (pos < 1) { throw SQLError.createSQLException(Messages.getString("Clob.2"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } if (str == null) { throw SQLError.createSQLException(Messages.getString("Clob.3"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } StringBuffer charBuf = new StringBuffer(this.charData); @@ -212,12 +217,12 @@ throws SQLException { if (pos < 1) { throw SQLError.createSQLException(Messages.getString("Clob.4"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } if (str == null) { throw SQLError.createSQLException(Messages.getString("Clob.5"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } StringBuffer charBuf = new StringBuffer(this.charData); @@ -243,7 +248,7 @@ if (streamSize < this.charData.length()) { try { out.write(StringUtils - .getBytes(this.charData, null, null, false, null), + .getBytes(this.charData, null, null, false, null, this.exceptionInterceptor), streamSize, this.charData.length() - streamSize); } catch (SQLException ex) { // @@ -261,7 +266,7 @@ throw SQLError.createSQLException( Messages.getString("Clob.11") //$NON-NLS-1$ + this.charData.length() - + Messages.getString("Clob.12") + length + Messages.getString("Clob.13")); //$NON-NLS-1$ //$NON-NLS-2$ + + Messages.getString("Clob.12") + length + Messages.getString("Clob.13"), this.exceptionInterceptor); //$NON-NLS-1$ //$NON-NLS-2$ } this.charData = this.charData.substring(0, (int) length); @@ -287,4 +292,12 @@ this.charData = out.toString(); } + + public void free() throws SQLException { + this.charData = null; + } + + public Reader getCharacterStream(long pos, long length) throws SQLException { + return new StringReader(getSubString(pos, (int)length)); + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CommunicationsException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CommunicationsException.java (.../CommunicationsException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CommunicationsException.java (.../CommunicationsException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,28 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import java.net.BindException; - import java.sql.SQLException; /** @@ -40,177 +37,50 @@ * @version $Id: CommunicationsException.java,v 1.1.2.1 2005/05/13 18:58:37 * mmatthews Exp $ */ -public class CommunicationsException extends SQLException { +public class CommunicationsException extends SQLException implements StreamingNotifiable { - private static final long DEFAULT_WAIT_TIMEOUT_SECONDS = 28800; + static final long serialVersionUID = 3193864990663398317L; - private static final int DUE_TO_TIMEOUT_FALSE = 0; + private String exceptionMessage = null; - private static final int DUE_TO_TIMEOUT_MAYBE = 2; - - private static final int DUE_TO_TIMEOUT_TRUE = 1; - - private String exceptionMessage; - private boolean streamingResultSetInPlay = false; - public CommunicationsException(Connection conn, long lastPacketSentTimeMs, - Exception underlyingException) { + private MySQLConnection conn; + private long lastPacketSentTimeMs; + private long lastPacketReceivedTimeMs; + private Exception underlyingException; - long serverTimeoutSeconds = 0; - boolean isInteractiveClient = false; - - if (conn != null) { - isInteractiveClient = conn.getInteractiveClient(); - - String serverTimeoutSecondsStr = null; - - if (isInteractiveClient) { - serverTimeoutSecondsStr = conn - .getServerVariable("interactive_timeout"); //$NON-NLS-1$ - } else { - serverTimeoutSecondsStr = conn - .getServerVariable("wait_timeout"); //$NON-NLS-1$ - } - - if (serverTimeoutSecondsStr != null) { - try { - serverTimeoutSeconds = Long - .parseLong(serverTimeoutSecondsStr); - } catch (NumberFormatException nfe) { - serverTimeoutSeconds = 0; - } - } - } - - StringBuffer exceptionMessageBuf = new StringBuffer(); - - if (lastPacketSentTimeMs == 0) { - lastPacketSentTimeMs = System.currentTimeMillis(); - } - - long timeSinceLastPacket = (System.currentTimeMillis() - lastPacketSentTimeMs) / 1000; - - int dueToTimeout = DUE_TO_TIMEOUT_FALSE; - - StringBuffer timeoutMessageBuf = null; - - if (this.streamingResultSetInPlay) { - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.ClientWasStreaming")); //$NON-NLS-1$ - } else { - if (serverTimeoutSeconds != 0) { - if (timeSinceLastPacket > serverTimeoutSeconds) { - dueToTimeout = DUE_TO_TIMEOUT_TRUE; - - timeoutMessageBuf = new StringBuffer(); - - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.2")); //$NON-NLS-1$ - - if (!isInteractiveClient) { - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.3")); //$NON-NLS-1$ - } else { - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.4")); //$NON-NLS-1$ - } - - } - } else if (timeSinceLastPacket > DEFAULT_WAIT_TIMEOUT_SECONDS) { - dueToTimeout = DUE_TO_TIMEOUT_MAYBE; - - timeoutMessageBuf = new StringBuffer(); - - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.5")); //$NON-NLS-1$ - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.6")); //$NON-NLS-1$ - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.7")); //$NON-NLS-1$ - timeoutMessageBuf.append(Messages - .getString("CommunicationsException.8")); //$NON-NLS-1$ - } - - if (dueToTimeout == DUE_TO_TIMEOUT_TRUE - || dueToTimeout == DUE_TO_TIMEOUT_MAYBE) { - - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.9")); //$NON-NLS-1$ - exceptionMessageBuf.append(timeSinceLastPacket); - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.10")); //$NON-NLS-1$ - - if (timeoutMessageBuf != null) { - exceptionMessageBuf.append(timeoutMessageBuf); - } - - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.11")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.12")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.13")); //$NON-NLS-1$ - - } else { - // - // Attempt to determine the reason for the underlying exception - // (we can only make a best-guess here) - // - - if (underlyingException instanceof BindException) { - if (conn.getLocalSocketAddress() != null && - !Util.interfaceExists(conn.getLocalSocketAddress())) { - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.19a")); //$NON-NLS-1$ - } else { - // too many client connections??? - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.14")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.15")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.16")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.17")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.18")); //$NON-NLS-1$ - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.19")); //$NON-NLS-1$ - } - } - } - } + public CommunicationsException(MySQLConnection conn, long lastPacketSentTimeMs, + long lastPacketReceivedTimeMs, Exception underlyingException) { - if (exceptionMessageBuf.length() == 0) { - // We haven't figured out a good reason, so copy it. - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.20")); //$NON-NLS-1$ - - if (underlyingException != null) { - exceptionMessageBuf.append(Messages - .getString("CommunicationsException.21")); //$NON-NLS-1$ - exceptionMessageBuf.append(Util - .stackTraceToString(underlyingException)); - } - - if (conn != null && conn.getMaintainTimeStats() && - !conn.getParanoid()) { - exceptionMessageBuf.append("\n\nLast packet sent to the server was "); - exceptionMessageBuf.append(System.currentTimeMillis() - lastPacketSentTimeMs); - exceptionMessageBuf.append(" ms ago."); - } + // store this information for later generation of message + this.conn = conn; + this.lastPacketReceivedTimeMs = lastPacketReceivedTimeMs; + this.lastPacketSentTimeMs = lastPacketSentTimeMs; + this.underlyingException = underlyingException; + + if (underlyingException != null) { + initCause(underlyingException); } - - this.exceptionMessage = exceptionMessageBuf.toString(); } + + /* * (non-Javadoc) * * @see java.lang.Throwable#getMessage() */ public String getMessage() { + // Get the message at last possible moment, but cache it + // and drop references to conn, underlyingException + if(this.exceptionMessage == null){ + this.exceptionMessage = SQLError.createLinkFailureMessageBasedOnHeuristics(this.conn, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, this.underlyingException, + this.streamingResultSetInPlay); + this.conn = null; + this.underlyingException = null; + } return this.exceptionMessage; } @@ -222,8 +92,11 @@ public String getSQLState() { return SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE; } - - protected void setWasStreamingResults() { + + /* (non-Javadoc) + * @see com.mysql.jdbc.StreamingNotifiable#setWasStreamingResults() + */ + public void setWasStreamingResults() { this.streamingResultSetInPlay = true; } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/CompressedInputStream.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/CompressedInputStream.java (.../CompressedInputStream.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/CompressedInputStream.java (.../CompressedInputStream.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,37 +1,36 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; - import java.sql.SQLException; - import java.util.zip.DataFormatException; import java.util.zip.Inflater; +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.log.NullLogger; /** * Used to de-compress packets from the MySQL server when protocol-level @@ -46,15 +45,18 @@ /** The packet data after it has been un-compressed */ private byte[] buffer; - /** The connection that is using us (used to read config values) */ - private Connection connection; - /** The stream we are reading from the server */ private InputStream in; /** The ZIP inflater used to un-compress packets */ private Inflater inflater; + /** Connection property reference */ + private ConnectionPropertiesImpl.BooleanConnectionProperty traceProtocol; + + /** Connection logger */ + private Log log; + /** * The buffer to read packet headers into */ @@ -72,7 +74,13 @@ * @param streamFromServer */ public CompressedInputStream(Connection conn, InputStream streamFromServer) { - this.connection = conn; + this.traceProtocol = ((ConnectionPropertiesImpl)conn).traceProtocol; + try { + this.log = conn.getLog(); + } catch (SQLException e) { + this.log = new NullLogger(null); + } + this.in = streamFromServer; this.inflater = new Inflater(); } @@ -94,7 +102,10 @@ public void close() throws IOException { this.in.close(); this.buffer = null; + this.inflater.end(); this.inflater = null; + this.traceProtocol = null; + this.log = null; } /** @@ -121,16 +132,13 @@ + (((this.packetHeaderBuffer[5] & 0xff)) << 8) + (((this.packetHeaderBuffer[6] & 0xff)) << 16); - if (this.connection.getTraceProtocol()) { - try { - this.connection.getLog().logTrace( - "Reading compressed packet of length " - + compressedPacketLength + " uncompressed to " - + uncompressedLength); - } catch (SQLException sqlEx) { - throw new IOException(sqlEx.toString()); // should never - // happen - } + boolean doTrace = this.traceProtocol.getValueAsBoolean(); + + if (doTrace) { + this.log.logTrace( + "Reading compressed packet of length " + + compressedPacketLength + " uncompressed to " + + uncompressedLength); } if (uncompressedLength > 0) { @@ -157,16 +165,9 @@ this.inflater.end(); } else { - if (this.connection.getTraceProtocol()) { - try { - this.connection - .getLog() - .logTrace( - "Packet didn't meet compression threshold, not uncompressing..."); - } catch (SQLException sqlEx) { - throw new IOException(sqlEx.toString()); // should never - // happen - } + if (doTrace) { + this.log.logTrace( + "Packet didn't meet compression threshold, not uncompressing..."); } // @@ -177,27 +178,17 @@ readFully(uncompressedData, 0, compressedPacketLength); } - if (this.connection.getTraceProtocol()) { - try { - this.connection.getLog().logTrace( + if (doTrace) { + this.log.logTrace( "Uncompressed packet: \n" + StringUtils.dumpAsHex(uncompressedData, compressedPacketLength)); - } catch (SQLException sqlEx) { - throw new IOException(sqlEx.toString()); // should never - // happen - } } if ((this.buffer != null) && (this.pos < this.buffer.length)) { - if (this.connection.getTraceProtocol()) { - try { - this.connection.getLog().logTrace( - "Combining remaining packet with new: "); - } catch (SQLException sqlEx) { - throw new IOException(sqlEx.toString()); // should never - // happen - } + if (doTrace) { + this.log.logTrace( + "Combining remaining packet with new: "); } int remaining = this.buffer.length - this.pos; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Connection.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Connection.java (.../Connection.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Connection.java (.../Connection.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,1851 +1,50 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import com.mysql.jdbc.log.Log; -import com.mysql.jdbc.log.LogFactory; -import com.mysql.jdbc.log.NullLogger; -import com.mysql.jdbc.profiler.ProfileEventSink; -import com.mysql.jdbc.profiler.ProfilerEvent; -import com.mysql.jdbc.util.LRUCache; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.UnsupportedEncodingException; - -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.math.BigDecimal; - -import java.net.URL; - -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.ParameterMetaData; -import java.sql.Ref; import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.Savepoint; -import java.sql.Time; -import java.sql.Timestamp; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; import java.util.Properties; -import java.util.Stack; -import java.util.StringTokenizer; import java.util.TimeZone; -import java.util.Timer; -import java.util.TreeMap; +import java.util.concurrent.Executor; +import com.mysql.jdbc.log.Log; + /** - * A Connection represents a session with a specific database. Within the - * context of a Connection, SQL statements are executed and results are - * returned. - *

- * A Connection's database is able to provide information describing its tables, - * its supported SQL grammar, its stored procedures, the capabilities of this - * connection, etc. This information is obtained with the getMetaData method. - *

+ * This interface contains methods that are considered the "vendor extension" + * to the JDBC API for MySQL's implementation of java.sql.Connection. * - * @author Mark Matthews + * For those looking further into the driver implementation, it is not + * an API that is used for plugability of implementations inside our driver + * (which is why there are still references to ConnectionImpl throughout the + * code). + * * @version $Id$ - * @see java.sql.Connection + * */ -public class Connection extends ConnectionProperties implements - java.sql.Connection { - private static final String JDBC_LOCAL_CHARACTER_SET_RESULTS = "jdbc.local.character_set_results"; +public interface Connection extends java.sql.Connection, ConnectionProperties { /** - * Used as a key for caching callable statements which (may) depend on - * current catalog...In 5.0.x, they don't (currently), but stored procedure - * names soon will, so current catalog is a (hidden) component of the name. - */ - class CompoundCacheKey { - String componentOne; - - String componentTwo; - - int hashCode; - - CompoundCacheKey(String partOne, String partTwo) { - this.componentOne = partOne; - this.componentTwo = partTwo; - - // Handle first component (in most cases, currentCatalog) - // being NULL.... - this.hashCode = (((this.componentOne != null) ? this.componentOne - : "") + this.componentTwo).hashCode(); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - if (obj instanceof CompoundCacheKey) { - CompoundCacheKey another = (CompoundCacheKey) obj; - - boolean firstPartEqual = false; - - if (this.componentOne == null) { - firstPartEqual = (another.componentOne == null); - } else { - firstPartEqual = this.componentOne - .equals(another.componentOne); - } - - return (firstPartEqual && this.componentTwo - .equals(another.componentTwo)); - } - - return false; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - return this.hashCode; - } - } - - /** - * Wrapper class for UltraDev CallableStatements that are really - * PreparedStatments. Nice going, UltraDev developers. - */ - class UltraDevWorkAround implements java.sql.CallableStatement { - private java.sql.PreparedStatement delegate = null; - - UltraDevWorkAround(java.sql.PreparedStatement pstmt) { - this.delegate = pstmt; - } - - public void addBatch() throws SQLException { - this.delegate.addBatch(); - } - - public void addBatch(java.lang.String p1) throws SQLException { - this.delegate.addBatch(p1); - } - - public void cancel() throws SQLException { - this.delegate.cancel(); - } - - public void clearBatch() throws SQLException { - this.delegate.clearBatch(); - } - - public void clearParameters() throws SQLException { - this.delegate.clearParameters(); - } - - public void clearWarnings() throws SQLException { - this.delegate.clearWarnings(); - } - - public void close() throws SQLException { - this.delegate.close(); - } - - public boolean execute() throws SQLException { - return this.delegate.execute(); - } - - public boolean execute(java.lang.String p1) throws SQLException { - return this.delegate.execute(p1); - } - - /** - * @see Statement#execute(String, int) - */ - public boolean execute(String arg0, int arg1) throws SQLException { - return this.delegate.execute(arg0, arg1); - } - - /** - * @see Statement#execute(String, int[]) - */ - public boolean execute(String arg0, int[] arg1) throws SQLException { - return this.delegate.execute(arg0, arg1); - } - - /** - * @see Statement#execute(String, String[]) - */ - public boolean execute(String arg0, String[] arg1) throws SQLException { - return this.delegate.execute(arg0, arg1); - } - - public int[] executeBatch() throws SQLException { - return this.delegate.executeBatch(); - } - - public java.sql.ResultSet executeQuery() throws SQLException { - return this.delegate.executeQuery(); - } - - public java.sql.ResultSet executeQuery(java.lang.String p1) - throws SQLException { - return this.delegate.executeQuery(p1); - } - - public int executeUpdate() throws SQLException { - return this.delegate.executeUpdate(); - } - - public int executeUpdate(java.lang.String p1) throws SQLException { - return this.delegate.executeUpdate(p1); - } - - /** - * @see Statement#executeUpdate(String, int) - */ - public int executeUpdate(String arg0, int arg1) throws SQLException { - return this.delegate.executeUpdate(arg0, arg1); - } - - /** - * @see Statement#executeUpdate(String, int[]) - */ - public int executeUpdate(String arg0, int[] arg1) throws SQLException { - return this.delegate.executeUpdate(arg0, arg1); - } - - /** - * @see Statement#executeUpdate(String, String[]) - */ - public int executeUpdate(String arg0, String[] arg1) - throws SQLException { - return this.delegate.executeUpdate(arg0, arg1); - } - - public java.sql.Array getArray(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getArray(String) - */ - public java.sql.Array getArray(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.math.BigDecimal getBigDecimal(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * DOCUMENT ME! - * - * @param p1 - * DOCUMENT ME! - * @param p2 - * DOCUMENT ME! - * @return DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - * @deprecated - */ - public java.math.BigDecimal getBigDecimal(int p1, int p2) - throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getBigDecimal(String) - */ - public BigDecimal getBigDecimal(String arg0) throws SQLException { - return null; - } - - public java.sql.Blob getBlob(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getBlob(String) - */ - public java.sql.Blob getBlob(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public boolean getBoolean(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getBoolean(String) - */ - public boolean getBoolean(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public byte getByte(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getByte(String) - */ - public byte getByte(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public byte[] getBytes(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getBytes(String) - */ - public byte[] getBytes(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.sql.Clob getClob(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getClob(String) - */ - public Clob getClob(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.sql.Connection getConnection() throws SQLException { - return this.delegate.getConnection(); - } - - public java.sql.Date getDate(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public java.sql.Date getDate(int p1, final Calendar p2) - throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getDate(String) - */ - public Date getDate(String arg0) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#getDate(String, Calendar) - */ - public Date getDate(String arg0, Calendar arg1) throws SQLException { - throw new NotImplemented(); - } - - public double getDouble(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getDouble(String) - */ - public double getDouble(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public int getFetchDirection() throws SQLException { - return this.delegate.getFetchDirection(); - } - - public int getFetchSize() throws java.sql.SQLException { - return this.delegate.getFetchSize(); - } - - public float getFloat(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getFloat(String) - */ - public float getFloat(String arg0) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see Statement#getGeneratedKeys() - */ - public java.sql.ResultSet getGeneratedKeys() throws SQLException { - return this.delegate.getGeneratedKeys(); - } - - public int getInt(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getInt(String) - */ - public int getInt(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public long getLong(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getLong(String) - */ - public long getLong(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public int getMaxFieldSize() throws SQLException { - return this.delegate.getMaxFieldSize(); - } - - public int getMaxRows() throws SQLException { - return this.delegate.getMaxRows(); - } - - public java.sql.ResultSetMetaData getMetaData() throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public boolean getMoreResults() throws SQLException { - return this.delegate.getMoreResults(); - } - - /** - * @see Statement#getMoreResults(int) - */ - public boolean getMoreResults(int arg0) throws SQLException { - return this.delegate.getMoreResults(); - } - - public java.lang.Object getObject(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public java.lang.Object getObject(int p1, final java.util.Map p2) - throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getObject(String) - */ - public Object getObject(String arg0) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#getObject(String, Map) - */ - public Object getObject(String arg0, Map arg1) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see PreparedStatement#getParameterMetaData() - */ - public ParameterMetaData getParameterMetaData() throws SQLException { - return this.delegate.getParameterMetaData(); - } - - public int getQueryTimeout() throws SQLException { - return this.delegate.getQueryTimeout(); - } - - public java.sql.Ref getRef(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getRef(String) - */ - public Ref getRef(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.sql.ResultSet getResultSet() throws SQLException { - return this.delegate.getResultSet(); - } - - public int getResultSetConcurrency() throws SQLException { - return this.delegate.getResultSetConcurrency(); - } - - /** - * @see Statement#getResultSetHoldability() - */ - public int getResultSetHoldability() throws SQLException { - return this.delegate.getResultSetHoldability(); - } - - public int getResultSetType() throws SQLException { - return this.delegate.getResultSetType(); - } - - public short getShort(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getShort(String) - */ - public short getShort(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.lang.String getString(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getString(String) - */ - public String getString(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.sql.Time getTime(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public java.sql.Time getTime(int p1, final java.util.Calendar p2) - throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getTime(String) - */ - public Time getTime(String arg0) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#getTime(String, Calendar) - */ - public Time getTime(String arg0, Calendar arg1) throws SQLException { - throw new NotImplemented(); - } - - public java.sql.Timestamp getTimestamp(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public java.sql.Timestamp getTimestamp(int p1, - final java.util.Calendar p2) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#getTimestamp(String) - */ - public Timestamp getTimestamp(String arg0) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#getTimestamp(String, Calendar) - */ - public Timestamp getTimestamp(String arg0, Calendar arg1) - throws SQLException { - throw new NotImplemented(); - } - - public int getUpdateCount() throws SQLException { - return this.delegate.getUpdateCount(); - } - - /** - * @see CallableStatement#getURL(int) - */ - public URL getURL(int arg0) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#getURL(String) - */ - public URL getURL(String arg0) throws SQLException { - throw new NotImplemented(); - } - - public java.sql.SQLWarning getWarnings() throws SQLException { - return this.delegate.getWarnings(); - } - - public void registerOutParameter(int p1, int p2) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public void registerOutParameter(int p1, int p2, int p3) - throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public void registerOutParameter(int p1, int p2, java.lang.String p3) - throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - /** - * @see CallableStatement#registerOutParameter(String, int) - */ - public void registerOutParameter(String arg0, int arg1) - throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#registerOutParameter(String, int, int) - */ - public void registerOutParameter(String arg0, int arg1, int arg2) - throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#registerOutParameter(String, int, String) - */ - public void registerOutParameter(String arg0, int arg1, String arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setArray(int p1, final java.sql.Array p2) - throws SQLException { - this.delegate.setArray(p1, p2); - } - - public void setAsciiStream(int p1, final java.io.InputStream p2, int p3) - throws SQLException { - this.delegate.setAsciiStream(p1, p2, p3); - } - - /** - * @see CallableStatement#setAsciiStream(String, InputStream, int) - */ - public void setAsciiStream(String arg0, InputStream arg1, int arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setBigDecimal(int p1, final java.math.BigDecimal p2) - throws SQLException { - this.delegate.setBigDecimal(p1, p2); - } - - /** - * @see CallableStatement#setBigDecimal(String, BigDecimal) - */ - public void setBigDecimal(String arg0, BigDecimal arg1) - throws SQLException { - throw new NotImplemented(); - } - - public void setBinaryStream(int p1, final java.io.InputStream p2, int p3) - throws SQLException { - this.delegate.setBinaryStream(p1, p2, p3); - } - - /** - * @see CallableStatement#setBinaryStream(String, InputStream, int) - */ - public void setBinaryStream(String arg0, InputStream arg1, int arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setBlob(int p1, final java.sql.Blob p2) throws SQLException { - this.delegate.setBlob(p1, p2); - } - - public void setBoolean(int p1, boolean p2) throws SQLException { - this.delegate.setBoolean(p1, p2); - } - - /** - * @see CallableStatement#setBoolean(String, boolean) - */ - public void setBoolean(String arg0, boolean arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setByte(int p1, byte p2) throws SQLException { - this.delegate.setByte(p1, p2); - } - - /** - * @see CallableStatement#setByte(String, byte) - */ - public void setByte(String arg0, byte arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setBytes(int p1, byte[] p2) throws SQLException { - this.delegate.setBytes(p1, p2); - } - - /** - * @see CallableStatement#setBytes(String, byte[]) - */ - public void setBytes(String arg0, byte[] arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setCharacterStream(int p1, final java.io.Reader p2, int p3) - throws SQLException { - this.delegate.setCharacterStream(p1, p2, p3); - } - - /** - * @see CallableStatement#setCharacterStream(String, Reader, int) - */ - public void setCharacterStream(String arg0, Reader arg1, int arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setClob(int p1, final java.sql.Clob p2) throws SQLException { - this.delegate.setClob(p1, p2); - } - - public void setCursorName(java.lang.String p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public void setDate(int p1, final java.sql.Date p2) throws SQLException { - this.delegate.setDate(p1, p2); - } - - public void setDate(int p1, final java.sql.Date p2, - final java.util.Calendar p3) throws SQLException { - this.delegate.setDate(p1, p2, p3); - } - - /** - * @see CallableStatement#setDate(String, Date) - */ - public void setDate(String arg0, Date arg1) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#setDate(String, Date, Calendar) - */ - public void setDate(String arg0, Date arg1, Calendar arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setDouble(int p1, double p2) throws SQLException { - this.delegate.setDouble(p1, p2); - } - - /** - * @see CallableStatement#setDouble(String, double) - */ - public void setDouble(String arg0, double arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setEscapeProcessing(boolean p1) throws SQLException { - this.delegate.setEscapeProcessing(p1); - } - - public void setFetchDirection(int p1) throws SQLException { - this.delegate.setFetchDirection(p1); - } - - public void setFetchSize(int p1) throws SQLException { - this.delegate.setFetchSize(p1); - } - - public void setFloat(int p1, float p2) throws SQLException { - this.delegate.setFloat(p1, p2); - } - - /** - * @see CallableStatement#setFloat(String, float) - */ - public void setFloat(String arg0, float arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setInt(int p1, int p2) throws SQLException { - this.delegate.setInt(p1, p2); - } - - /** - * @see CallableStatement#setInt(String, int) - */ - public void setInt(String arg0, int arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setLong(int p1, long p2) throws SQLException { - this.delegate.setLong(p1, p2); - } - - /** - * @see CallableStatement#setLong(String, long) - */ - public void setLong(String arg0, long arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setMaxFieldSize(int p1) throws SQLException { - this.delegate.setMaxFieldSize(p1); - } - - public void setMaxRows(int p1) throws SQLException { - this.delegate.setMaxRows(p1); - } - - public void setNull(int p1, int p2) throws SQLException { - this.delegate.setNull(p1, p2); - } - - public void setNull(int p1, int p2, java.lang.String p3) - throws SQLException { - this.delegate.setNull(p1, p2, p3); - } - - /** - * @see CallableStatement#setNull(String, int) - */ - public void setNull(String arg0, int arg1) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#setNull(String, int, String) - */ - public void setNull(String arg0, int arg1, String arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setObject(int p1, final java.lang.Object p2) - throws SQLException { - this.delegate.setObject(p1, p2); - } - - public void setObject(int p1, final java.lang.Object p2, int p3) - throws SQLException { - this.delegate.setObject(p1, p2, p3); - } - - public void setObject(int p1, final java.lang.Object p2, int p3, int p4) - throws SQLException { - this.delegate.setObject(p1, p2, p3, p4); - } - - /** - * @see CallableStatement#setObject(String, Object) - */ - public void setObject(String arg0, Object arg1) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#setObject(String, Object, int) - */ - public void setObject(String arg0, Object arg1, int arg2) - throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#setObject(String, Object, int, int) - */ - public void setObject(String arg0, Object arg1, int arg2, int arg3) - throws SQLException { - throw new NotImplemented(); - } - - public void setQueryTimeout(int p1) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public void setRef(int p1, final Ref p2) throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - - public void setShort(int p1, short p2) throws SQLException { - this.delegate.setShort(p1, p2); - } - - /** - * @see CallableStatement#setShort(String, short) - */ - public void setShort(String arg0, short arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setString(int p1, java.lang.String p2) - throws java.sql.SQLException { - this.delegate.setString(p1, p2); - } - - /** - * @see CallableStatement#setString(String, String) - */ - public void setString(String arg0, String arg1) throws SQLException { - throw new NotImplemented(); - } - - public void setTime(int p1, final java.sql.Time p2) throws SQLException { - this.delegate.setTime(p1, p2); - } - - public void setTime(int p1, final java.sql.Time p2, - final java.util.Calendar p3) throws SQLException { - this.delegate.setTime(p1, p2, p3); - } - - /** - * @see CallableStatement#setTime(String, Time) - */ - public void setTime(String arg0, Time arg1) throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#setTime(String, Time, Calendar) - */ - public void setTime(String arg0, Time arg1, Calendar arg2) - throws SQLException { - throw new NotImplemented(); - } - - public void setTimestamp(int p1, final java.sql.Timestamp p2) - throws SQLException { - this.delegate.setTimestamp(p1, p2); - } - - public void setTimestamp(int p1, final java.sql.Timestamp p2, - final java.util.Calendar p3) throws SQLException { - this.delegate.setTimestamp(p1, p2, p3); - } - - /** - * @see CallableStatement#setTimestamp(String, Timestamp) - */ - public void setTimestamp(String arg0, Timestamp arg1) - throws SQLException { - throw new NotImplemented(); - } - - /** - * @see CallableStatement#setTimestamp(String, Timestamp, Calendar) - */ - public void setTimestamp(String arg0, Timestamp arg1, Calendar arg2) - throws SQLException { - throw new NotImplemented(); - } - - /** - * DOCUMENT ME! - * - * @param p1 - * DOCUMENT ME! - * @param p2 - * DOCUMENT ME! - * @param p3 - * DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - * @deprecated - */ - public void setUnicodeStream(int p1, final java.io.InputStream p2, - int p3) throws SQLException { - this.delegate.setUnicodeStream(p1, p2, p3); - } - - /** - * @see PreparedStatement#setURL(int, URL) - */ - public void setURL(int arg0, URL arg1) throws SQLException { - this.delegate.setURL(arg0, arg1); - } - - /** - * @see CallableStatement#setURL(String, URL) - */ - public void setURL(String arg0, URL arg1) throws SQLException { - throw new NotImplemented(); - } - - public boolean wasNull() throws SQLException { - throw SQLError.createSQLException("Not supported"); - } - } - - /** - * Marker for character set converter not being available (not written, - * multibyte, etc) Used to prevent multiple instantiation requests. - */ - private static final Object CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object(); - - /** - * The mapping between MySQL charset names and Java charset names. - * Initialized by loadCharacterSetMapping() - */ - public static Map charsetMap; - - /** Default logger class name */ - protected static final String DEFAULT_LOGGER_CLASS = "com.mysql.jdbc.log.StandardLogger"; - - private final static int HISTOGRAM_BUCKETS = 20; - - /** Logger instance name */ - private static final String LOGGER_INSTANCE_NAME = "MySQL"; - - /** - * Map mysql transaction isolation level name to - * java.sql.Connection.TRANSACTION_XXX - */ - private static Map mapTransIsolationNameToValue = null; - - /** Null logger shared by all connections at startup */ - private static final Log NULL_LOGGER = new NullLogger(LOGGER_INSTANCE_NAME); - - private static Map roundRobinStatsMap; - - private static final Map serverCollationByUrl = new HashMap(); - - private static final Map serverConfigByUrl = new HashMap(); - - private static Timer cancelTimer; - - static { - mapTransIsolationNameToValue = new HashMap(8); - mapTransIsolationNameToValue.put("READ-UNCOMMITED", new Integer( - TRANSACTION_READ_UNCOMMITTED)); - mapTransIsolationNameToValue.put("READ-UNCOMMITTED", new Integer( - TRANSACTION_READ_UNCOMMITTED)); - mapTransIsolationNameToValue.put("READ-COMMITTED", new Integer( - TRANSACTION_READ_COMMITTED)); - mapTransIsolationNameToValue.put("REPEATABLE-READ", new Integer( - TRANSACTION_REPEATABLE_READ)); - mapTransIsolationNameToValue.put("SERIALIZABLE", new Integer( - TRANSACTION_SERIALIZABLE)); - - boolean createdNamedTimer = false; - - // Use reflection magic to try this on JDK's 1.5 and newer, fallback to non-named - // timer on older VMs. - try { - Constructor ctr = Timer.class.getConstructor(new Class[] {String.class, Boolean.TYPE}); - - cancelTimer = (Timer)ctr.newInstance(new Object[] { "MySQL Statement Cancellation Timer", Boolean.TRUE}); - createdNamedTimer = true; - } catch (Throwable t) { - createdNamedTimer = false; - } - - if (!createdNamedTimer) { - cancelTimer = new Timer(true); - } - } - - protected static SQLException appendMessageToException(SQLException sqlEx, - String messageToAppend) { - String origMessage = sqlEx.getMessage(); - String sqlState = sqlEx.getSQLState(); - int vendorErrorCode = sqlEx.getErrorCode(); - - StringBuffer messageBuf = new StringBuffer(origMessage.length() - + messageToAppend.length()); - messageBuf.append(origMessage); - messageBuf.append(messageToAppend); - - SQLException sqlExceptionWithNewMessage = SQLError.createSQLException(messageBuf - .toString(), sqlState, vendorErrorCode); - - // - // Try and maintain the original stack trace, - // only works on JDK-1.4 and newer - // - - try { - // Have to do this with reflection, otherwise older JVMs croak - Method getStackTraceMethod = null; - Method setStackTraceMethod = null; - Object theStackTraceAsObject = null; - - Class stackTraceElementClass = Class - .forName("java.lang.StackTraceElement"); - Class stackTraceElementArrayClass = Array.newInstance( - stackTraceElementClass, new int[] { 0 }).getClass(); - - getStackTraceMethod = Throwable.class.getMethod("getStackTrace", - new Class[] {}); - - setStackTraceMethod = Throwable.class.getMethod("setStackTrace", - new Class[] { stackTraceElementArrayClass }); - - if (getStackTraceMethod != null && setStackTraceMethod != null) { - theStackTraceAsObject = getStackTraceMethod.invoke(sqlEx, - new Object[0]); - setStackTraceMethod.invoke(sqlExceptionWithNewMessage, - new Object[] { theStackTraceAsObject }); - } - } catch (NoClassDefFoundError noClassDefFound) { - - } catch (NoSuchMethodException noSuchMethodEx) { - - } catch (Throwable catchAll) { - - } - - return sqlExceptionWithNewMessage; - } - - protected static Timer getCancelTimer() { - return cancelTimer; - } - - private static synchronized int getNextRoundRobinHostIndex(String url, - List hostList) { - if (roundRobinStatsMap == null) { - roundRobinStatsMap = new HashMap(); - } - - int[] index = (int[]) roundRobinStatsMap.get(url); - - if (index == null) { - index = new int[1]; - index[0] = -1; - - roundRobinStatsMap.put(url, index); - } - - index[0]++; - - if (index[0] >= hostList.size()) { - index[0] = 0; - } - - return index[0]; - } - - private static boolean nullSafeCompare(String s1, String s2) { - if (s1 == null && s2 == null) { - return true; - } - - if (s1 == null && s2 != null) { - return false; - } - - return s1.equals(s2); - } - - /** Are we in autoCommit mode? */ - private boolean autoCommit = true; - - /** A map of SQL to parsed prepared statement parameters. */ - private Map cachedPreparedStatementParams; - - /** - * For servers > 4.1.0, what character set is the metadata returned in? - */ - private String characterSetMetadata = null; - - /** - * The character set we want results and result metadata returned in (null == - * results in any charset, metadata in UTF-8). - */ - private String characterSetResultsOnServer = null; - - /** - * Holds cached mappings to charset converters to avoid static - * synchronization and at the same time save memory (each charset converter - * takes approx 65K of static data). - */ - private Map charsetConverterMap = new HashMap(CharsetMapping - .getNumberOfCharsetsConfigured()); - - /** - * The mapping between MySQL charset names and the max number of chars in - * them. Lazily instantiated via getMaxBytesPerChar(). - */ - private Map charsetToNumBytesMap; - - /** The point in time when this connection was created */ - private long connectionCreationTimeMillis = 0; - - /** ID used when profiling */ - private long connectionId; - - /** The database we're currently using (called Catalog in JDBC terms). */ - private String database = null; - - /** Internal DBMD to use for various database-version specific features */ - private DatabaseMetaData dbmd = null; - - private TimeZone defaultTimeZone; - - /** The event sink to use for profiling */ - private ProfileEventSink eventSink; - - private boolean executingFailoverReconnect = false; - - /** Are we failed-over to a non-master host */ - private boolean failedOver = false; - - /** Why was this connection implicitly closed, if known? (for diagnostics) */ - private Throwable forceClosedReason; - - /** Where was this connection implicitly closed? (for diagnostics) */ - private Throwable forcedClosedLocation; - - /** Does the server suuport isolation levels? */ - private boolean hasIsolationLevels = false; - - /** Does this version of MySQL support quoted identifiers? */ - private boolean hasQuotedIdentifiers = false; - - /** The hostname we're connected to */ - private String host = null; - - /** The list of host(s) to try and connect to */ - private List hostList = null; - - /** How many hosts are in the host list? */ - private int hostListSize = 0; - - /** - * We need this 'bootstrapped', because 4.1 and newer will send fields back - * with this even before we fill this dynamically from the server. - */ - private String[] indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET; - - /** The I/O abstraction interface (network conn to MySQL server */ - private MysqlIO io = null; - - private boolean isClientTzUTC = false; - - /** Has this connection been closed? */ - private boolean isClosed = true; - - /** Is this connection associated with a global tx? */ - private boolean isInGlobalTx = false; - - /** Is this connection running inside a JDK-1.3 VM? */ - private boolean isRunningOnJDK13 = false; - - /** isolation level */ - private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED; - - private boolean isServerTzUTC = false; - - /** When did the last query finish? */ - private long lastQueryFinishedTime = 0; - - /** The logger we're going to use */ - private Log log = NULL_LOGGER; - - /** - * If gathering metrics, what was the execution time of the longest query so - * far ? - */ - private long longestQueryTimeMs = 0; - - /** Is the server configured to use lower-case table names only? */ - private boolean lowerCaseTableNames = false; - - /** When did the master fail? */ - private long masterFailTimeMillis = 0L; - - /** - * The largest packet we can send (changed once we know what the server - * supports, we get this at connection init). - */ - private int maxAllowedPacket = 65536; - - private long maximumNumberTablesAccessed = 0; - - /** Has the max-rows setting been changed from the default? */ - private boolean maxRowsChanged = false; - - /** When was the last time we reported metrics? */ - private long metricsLastReportedMs; - - private long minimumNumberTablesAccessed = Long.MAX_VALUE; - - /** Mutex */ - private final Object mutex = new Object(); - - /** The JDBC URL we're using */ - private String myURL = null; - - /** Does this connection need to be tested? */ - private boolean needsPing = false; - - private int netBufferLength = 16384; - - private boolean noBackslashEscapes = false; - - private long numberOfPreparedExecutes = 0; - - private long numberOfPrepares = 0; - - private long numberOfQueriesIssued = 0; - - private long numberOfResultSetsCreated = 0; - - private long[] numTablesMetricsHistBreakpoints; - - private int[] numTablesMetricsHistCounts; - - private long[] oldHistBreakpoints = null; - - private int[] oldHistCounts = null; - - /** A map of currently open statements */ - private Map openStatements; - - private LRUCache parsedCallableStatementCache; - - private boolean parserKnowsUnicode = false; - - /** The password we used */ - private String password = null; - - private long[] perfMetricsHistBreakpoints; - - private int[] perfMetricsHistCounts; - - /** Point of origin where this Connection was created */ - private Throwable pointOfOrigin; - - /** The port number we're connected to (defaults to 3306) */ - private int port = 3306; - - /** - * Used only when testing failover functionality for regressions, causes the - * failover code to not retry the master first - */ - private boolean preferSlaveDuringFailover = false; - - /** Properties for this connection specified by user */ - private Properties props = null; - - /** Number of queries we've issued since the master failed */ - private long queriesIssuedFailedOver = 0; - - /** Should we retrieve 'info' messages from the server? */ - private boolean readInfoMsg = false; - - /** Are we in read-only mode? */ - private boolean readOnly = false; - - /** Cache of ResultSet metadata */ - protected LRUCache resultSetMetadataCache; - - /** The timezone of the server */ - private TimeZone serverTimezoneTZ = null; - - /** The map of server variables that we retrieve at connection init. */ - private Map serverVariables = null; - - private long shortestQueryTimeMs = Long.MAX_VALUE; - - /** A map of statements that have had setMaxRows() called on them */ - private Map statementsUsingMaxRows; - - private double totalQueryTimeMs = 0; - - /** Are transactions supported by the MySQL server we are connected to? */ - private boolean transactionsSupported = false; - - /** - * The type map for UDTs (not implemented, but used by some third-party - * vendors, most notably IBM WebSphere) - */ - private Map typeMap; - - /** Has ANSI_QUOTES been enabled on the server? */ - private boolean useAnsiQuotes = false; - - /** The user we're connected as */ - private String user = null; - - /** - * Should we use server-side prepared statements? (auto-detected, but can be - * disabled by user) - */ - private boolean useServerPreparedStmts = false; - - private LRUCache serverSideStatementCheckCache; - - private LRUCache serverSideStatementCache; - private Calendar sessionCalendar; - private Calendar utcCalendar; - - private String origHostToConnectTo; - - private int origPortToConnectTo; - - // we don't want to be able to publicly clone this... - - private String origDatabaseToConnectTo; - - private String errorMessageEncoding = "Cp1252"; // to begin with, changes after we talk to the server - - private boolean usePlatformCharsetConverters; - - - /** - * Creates a connection to a MySQL Server. - * - * @param hostToConnectTo - * the hostname of the database server - * @param portToConnectTo - * the port number the server is listening on - * @param info - * a Properties[] list holding the user and password - * @param databaseToConnectTo - * the database to connect to - * @param url - * the URL of the connection - * @param d - * the Driver instantation of the connection - * @exception SQLException - * if a database access error occurs - */ - Connection(String hostToConnectTo, int portToConnectTo, Properties info, - String databaseToConnectTo, String url) - throws SQLException { - this.charsetToNumBytesMap = new HashMap(); - - this.connectionCreationTimeMillis = System.currentTimeMillis(); - this.pointOfOrigin = new Throwable(); - - // Stash away for later, used to clone this connection for Statement.cancel - // and Statement.setQueryTimeout(). - // - - this.origHostToConnectTo = hostToConnectTo; - this.origPortToConnectTo = portToConnectTo; - this.origDatabaseToConnectTo = databaseToConnectTo; - - try { - Blob.class.getMethod("truncate", new Class[] {Long.TYPE}); - - this.isRunningOnJDK13 = false; - } catch (NoSuchMethodException nsme) { - this.isRunningOnJDK13 = true; - } - - this.sessionCalendar = new GregorianCalendar(); - this.utcCalendar = new GregorianCalendar(); - this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT")); - - // - // Normally, this code would be in initializeDriverProperties, - // but we need to do this as early as possible, so we can start - // logging to the 'correct' place as early as possible...this.log - // points to 'NullLogger' for every connection at startup to avoid - // NPEs and the overhead of checking for NULL at every logging call. - // - // We will reset this to the configured logger during properties - // initialization. - // - this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME); - - // We store this per-connection, due to static synchronization - // issues in Java's built-in TimeZone class... - this.defaultTimeZone = Util.getDefaultTimeZone(); - - if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) { - this.isClientTzUTC = true; - } else { - this.isClientTzUTC = false; - } - - this.openStatements = new HashMap(); - this.serverVariables = new HashMap(); - this.hostList = new ArrayList(); - - if (hostToConnectTo == null) { - this.host = "localhost"; - this.hostList.add(this.host); - } else if (hostToConnectTo.indexOf(",") != -1) { - // multiple hosts separated by commas (failover) - StringTokenizer hostTokenizer = new StringTokenizer( - hostToConnectTo, ",", false); - - while (hostTokenizer.hasMoreTokens()) { - this.hostList.add(hostTokenizer.nextToken().trim()); - } - } else { - this.host = hostToConnectTo; - this.hostList.add(this.host); - } - - this.hostListSize = this.hostList.size(); - this.port = portToConnectTo; - - if (databaseToConnectTo == null) { - databaseToConnectTo = ""; - } - - this.database = databaseToConnectTo; - this.myURL = url; - this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY); - this.password = info - .getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY); - - if ((this.user == null) || this.user.equals("")) { - this.user = ""; - } - - if (this.password == null) { - this.password = ""; - } - - this.props = info; - initializeDriverProperties(info); - - try { - createNewIO(false); - this.dbmd = new DatabaseMetaData(this, this.database); - } catch (SQLException ex) { - cleanup(ex); - - // don't clobber SQL exceptions - throw ex; - } catch (Exception ex) { - cleanup(ex); - - StringBuffer mesg = new StringBuffer(); - - if (getParanoid()) { - mesg.append("Cannot connect to MySQL server on "); - mesg.append(this.host); - mesg.append(":"); - mesg.append(this.port); - mesg.append(".\n\n"); - mesg.append("Make sure that there is a MySQL server "); - mesg.append("running on the machine/port you are trying "); - mesg - .append("to connect to and that the machine this software is " - + "running on "); - mesg.append("is able to connect to this host/port " - + "(i.e. not firewalled). "); - mesg - .append("Also make sure that the server has not been started " - + "with the --skip-networking "); - mesg.append("flag.\n\n"); - } else { - mesg.append("Unable to connect to database."); - } - - mesg.append("Underlying exception: \n\n"); - mesg.append(ex.getClass().getName()); - - if (!getParanoid()) { - mesg.append(Util.stackTraceToString(ex)); - } - - throw SQLError.createSQLException(mesg.toString(), - SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE); - } - } - - private void addToHistogram(int[] histogramCounts, - long[] histogramBreakpoints, long value, int numberOfTimes, - long currentLowerBound, long currentUpperBound) { - if (histogramCounts == null) { - createInitialHistogram(histogramBreakpoints, - currentLowerBound, currentUpperBound); - } - - for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { - if (histogramBreakpoints[i] >= value) { - histogramCounts[i] += numberOfTimes; - - break; - } - } - } - - private void addToPerformanceHistogram(long value, int numberOfTimes) { - checkAndCreatePerformanceHistogram(); - - addToHistogram(this.perfMetricsHistCounts, - this.perfMetricsHistBreakpoints, value, numberOfTimes, - this.shortestQueryTimeMs == Long.MAX_VALUE ? 0 - : this.shortestQueryTimeMs, this.longestQueryTimeMs); - } - - private void addToTablesAccessedHistogram(long value, int numberOfTimes) { - checkAndCreateTablesAccessedHistogram(); - - addToHistogram(this.numTablesMetricsHistCounts, - this.numTablesMetricsHistBreakpoints, value, numberOfTimes, - this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0 - : this.minimumNumberTablesAccessed, - this.maximumNumberTablesAccessed); - } - - /** - * Builds the map needed for 4.1.0 and newer servers that maps field-level - * charset/collation info to a java character encoding name. - * - * @throws SQLException - * DOCUMENT ME! - */ - private void buildCollationMapping() throws SQLException { - if (versionMeetsMinimum(4, 1, 0)) { - - TreeMap sortedCollationMap = null; - - if (getCacheServerConfiguration()) { - synchronized (serverConfigByUrl) { - sortedCollationMap = (TreeMap) serverCollationByUrl - .get(getURL()); - } - } - - com.mysql.jdbc.Statement stmt = null; - com.mysql.jdbc.ResultSet results = null; - - try { - if (sortedCollationMap == null) { - sortedCollationMap = new TreeMap(); - - stmt = (com.mysql.jdbc.Statement) createStatement(); - - if (stmt.getMaxRows() != 0) { - stmt.setMaxRows(0); - } - - results = (com.mysql.jdbc.ResultSet) stmt - .executeQuery("SHOW COLLATION"); - - while (results.next()) { - String charsetName = results.getString(2); - Integer charsetIndex = new Integer(results.getInt(3)); - - sortedCollationMap.put(charsetIndex, charsetName); - } - - if (getCacheServerConfiguration()) { - synchronized (serverConfigByUrl) { - serverCollationByUrl.put(getURL(), - sortedCollationMap); - } - } - - } - - // Now, merge with what we already know - int highestIndex = ((Integer) sortedCollationMap.lastKey()) - .intValue(); - - if (CharsetMapping.INDEX_TO_CHARSET.length > highestIndex) { - highestIndex = CharsetMapping.INDEX_TO_CHARSET.length; - } - - this.indexToCharsetMapping = new String[highestIndex + 1]; - - for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) { - this.indexToCharsetMapping[i] = CharsetMapping.INDEX_TO_CHARSET[i]; - } - - for (Iterator indexIter = sortedCollationMap.entrySet() - .iterator(); indexIter.hasNext();) { - Map.Entry indexEntry = (Map.Entry) indexIter.next(); - - String mysqlCharsetName = (String) indexEntry.getValue(); - - this.indexToCharsetMapping[((Integer) indexEntry.getKey()) - .intValue()] = CharsetMapping - .getJavaEncodingForMysqlEncoding(mysqlCharsetName, - this); - } - } catch (java.sql.SQLException e) { - throw e; - } finally { - if (results != null) { - try { - results.close(); - } catch (java.sql.SQLException sqlE) { - ; - } - } - - if (stmt != null) { - try { - stmt.close(); - } catch (java.sql.SQLException sqlE) { - ; - } - } - } - } else { - // Safety, we already do this as an initializer, but this makes - // the intent more clear - this.indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET; - } - } - - private boolean canHandleAsServerPreparedStatement(String sql) - throws SQLException { - if (sql == null || sql.length() == 0) { - return true; - } - - if (getCachePreparedStatements()) { - synchronized (this.serverSideStatementCheckCache) { - Boolean flag = (Boolean)this.serverSideStatementCheckCache.get(sql); - - if (flag != null) { - return flag.booleanValue(); - } - - boolean canHandle = canHandleAsServerPreparedStatementNoCache(sql); - - if (sql.length() < getPreparedStatementCacheSqlLimit()) { - this.serverSideStatementCheckCache.put(sql, - canHandle ? Boolean.TRUE : Boolean.FALSE); - } - - return canHandle; - } - } - - return canHandleAsServerPreparedStatementNoCache(sql); - } - - private boolean canHandleAsServerPreparedStatementNoCache(String sql) - throws SQLException { - - // Can't use server-side prepare for CALL - if (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "CALL")) { - return false; - } - - boolean canHandleAsStatement = true; - - if (!versionMeetsMinimum(5, 0, 7) && - (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "SELECT") - || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, - "DELETE") - || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, - "INSERT") - || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, - "UPDATE") - || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, - "REPLACE"))) { - - // check for limit ?[,?] - - /* - * The grammar for this (from the server) is: ULONG_NUM | ULONG_NUM - * ',' ULONG_NUM | ULONG_NUM OFFSET_SYM ULONG_NUM - */ - - int currentPos = 0; - int statementLength = sql.length(); - int lastPosToLook = statementLength - 7; // "LIMIT ".length() - boolean allowBackslashEscapes = !this.noBackslashEscapes; - char quoteChar = this.useAnsiQuotes ? '"' : '\''; - boolean foundLimitWithPlaceholder = false; - - while (currentPos < lastPosToLook) { - int limitStart = StringUtils.indexOfIgnoreCaseRespectQuotes( - currentPos, sql, "LIMIT ", quoteChar, - allowBackslashEscapes); - - if (limitStart == -1) { - break; - } - - currentPos = limitStart + 7; - - while (currentPos < statementLength) { - char c = sql.charAt(currentPos); - - // - // Have we reached the end - // of what can be in a LIMIT clause? - // - - if (!Character.isDigit(c) && !Character.isWhitespace(c) - && c != ',' && c != '?') { - break; - } - - if (c == '?') { - foundLimitWithPlaceholder = true; - break; - } - - currentPos++; - } - } - - canHandleAsStatement = !foundLimitWithPlaceholder; - } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "CREATE TABLE")) { - canHandleAsStatement = false; - } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "DO")) { - canHandleAsStatement = false; - } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "SET")) { - canHandleAsStatement = false; - } - - - - return canHandleAsStatement; - } - - /** * Changes the user on this connection by performing a re-authentication. If * authentication fails, the connection will remain under the context of the * current user. @@ -1858,4137 +57,382 @@ * if authentication fails, or some other error occurs while * performing the command. */ - public void changeUser(String userName, String newPassword) - throws SQLException { - if ((userName == null) || userName.equals("")) { - userName = ""; - } + public abstract void changeUser(String userName, String newPassword) + throws SQLException; - if (newPassword == null) { - newPassword = ""; - } + public abstract void clearHasTriedMaster(); - this.io.changeUser(userName, newPassword, this.database); - this.user = userName; - this.password = newPassword; - - if (versionMeetsMinimum(4, 1, 0)) { - configureClientCharacterSet(); - } - - setupServerForTruncationChecks(); - } - - private void checkAndCreatePerformanceHistogram() { - if (this.perfMetricsHistCounts == null) { - this.perfMetricsHistCounts = new int[HISTOGRAM_BUCKETS]; - } - - if (this.perfMetricsHistBreakpoints == null) { - this.perfMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS]; - } - } - - private void checkAndCreateTablesAccessedHistogram() { - if (this.numTablesMetricsHistCounts == null) { - this.numTablesMetricsHistCounts = new int[HISTOGRAM_BUCKETS]; - } - - if (this.numTablesMetricsHistBreakpoints == null) { - this.numTablesMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS]; - } - } - - private void checkClosed() throws SQLException { - if (this.isClosed) { - StringBuffer messageBuf = new StringBuffer( - "No operations allowed after connection closed."); - - if (this.forcedClosedLocation != null || this.forceClosedReason != null) { - messageBuf - .append("Connection was implicitly closed "); - } - - if (this.forcedClosedLocation != null) { - messageBuf.append("\n\n"); - messageBuf - .append(" at (stack trace):\n"); - messageBuf.append(Util - .stackTraceToString(this.forcedClosedLocation)); - } - - if (this.forceClosedReason != null) { - if (this.forcedClosedLocation != null) { - messageBuf.append("\n\nDue "); - } else { - messageBuf.append("due "); - } - - messageBuf.append("to underlying exception/error:\n"); - messageBuf.append(Util - .stackTraceToString(this.forceClosedReason)); - } - - throw SQLError.createSQLException(messageBuf.toString(), - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); - } - } - /** - * If useUnicode flag is set and explicit client character encoding isn't - * specified then assign encoding from server if any. + * Prepares a statement on the client, using client-side emulation + * (irregardless of the configuration property 'useServerPrepStmts') + * with the same semantics as the java.sql.Connection.prepareStatement() + * method with the same argument types. * - * @throws SQLException - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String) */ - private void checkServerEncoding() throws SQLException { - if (getUseUnicode() && (getEncoding() != null)) { - // spec'd by client, don't map - return; - } + public abstract java.sql.PreparedStatement clientPrepareStatement(String sql) + throws SQLException; - String serverEncoding = (String) this.serverVariables - .get("character_set"); - - if (serverEncoding == null) { - // must be 4.1.1 or newer? - serverEncoding = (String) this.serverVariables - .get("character_set_server"); - } - - String mappedServerEncoding = null; - - if (serverEncoding != null) { - mappedServerEncoding = CharsetMapping - .getJavaEncodingForMysqlEncoding(serverEncoding - .toUpperCase(Locale.ENGLISH), this); - } - - // - // First check if we can do the encoding ourselves - // - if (!getUseUnicode() && (mappedServerEncoding != null)) { - SingleByteCharsetConverter converter = getCharsetConverter(mappedServerEncoding); - - if (converter != null) { // we know how to convert this ourselves - setUseUnicode(true); // force the issue - setEncoding(mappedServerEncoding); - - return; - } - } - - // - // Now, try and find a Java I/O converter that can do - // the encoding for us - // - if (serverEncoding != null) { - if (mappedServerEncoding == null) { - // We don't have a mapping for it, so try - // and canonicalize the name.... - if (Character.isLowerCase(serverEncoding.charAt(0))) { - char[] ach = serverEncoding.toCharArray(); - ach[0] = Character.toUpperCase(serverEncoding.charAt(0)); - setEncoding(new String(ach)); - } - } - - if (mappedServerEncoding == null) { - throw SQLError.createSQLException("Unknown character encoding on server '" - + serverEncoding - + "', use 'characterEncoding=' property " - + " to provide correct mapping", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - - // - // Attempt to use the encoding, and bail out if it - // can't be used - // - try { - "abc".getBytes(mappedServerEncoding); - setEncoding(mappedServerEncoding); - setUseUnicode(true); - } catch (UnsupportedEncodingException UE) { - throw SQLError.createSQLException( - "The driver can not map the character encoding '" - + getEncoding() - + "' that your server is using " - + "to a character encoding your JVM understands. You " - + "can specify this mapping manually by adding \"useUnicode=true\" " - + "as well as \"characterEncoding=[an_encoding_your_jvm_understands]\" " - + "to your JDBC URL.", "0S100"); - } - } - } - /** - * Set transaction isolation level to the value received from server if any. - * Is called by connectionInit(...) + * Prepares a statement on the client, using client-side emulation + * (irregardless of the configuration property 'useServerPrepStmts') + * with the same semantics as the java.sql.Connection.prepareStatement() + * method with the same argument types. * - * @throws SQLException - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String, int) */ - private void checkTransactionIsolationLevel() throws SQLException { - String txIsolationName = null; + public abstract java.sql.PreparedStatement clientPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException; - if (versionMeetsMinimum(4, 0, 3)) { - txIsolationName = "tx_isolation"; - } else { - txIsolationName = "transaction_isolation"; - } - - String s = (String) this.serverVariables.get(txIsolationName); - - if (s != null) { - Integer intTI = (Integer) mapTransIsolationNameToValue.get(s); - - if (intTI != null) { - this.isolationLevel = intTI.intValue(); - } - } - } - /** - * Destroys this connection and any underlying resources + * Prepares a statement on the client, using client-side emulation + * (irregardless of the configuration property 'useServerPrepStmts') + * with the same semantics as the java.sql.Connection.prepareStatement() + * method with the same argument types. * - * @param fromWhere - * DOCUMENT ME! - * @param whyCleanedUp - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String, int, int) */ - private void cleanup(Throwable whyCleanedUp) { - try { - if ((this.io != null) && !isClosed()) { - realClose(false, false, false, whyCleanedUp); - } else if (this.io != null) { - this.io.forceClose(); - } - } catch (SQLException sqlEx) { - // ignore, we're going away. - ; - } + public abstract java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException; - this.isClosed = true; - } - /** - * After this call, getWarnings returns null until a new warning is reported - * for this connection. + * Prepares a statement on the client, using client-side emulation + * (irregardless of the configuration property 'useServerPrepStmts') + * with the same semantics as the java.sql.Connection.prepareStatement() + * method with the same argument types. * - * @exception SQLException - * if a database access error occurs + * @see java.sql.Connection#prepareStatement(String, int[]) */ - public void clearWarnings() throws SQLException { - // firstWarning = null; - } + public abstract java.sql.PreparedStatement clientPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException; /** - * DOCUMENT ME! + * Prepares a statement on the client, using client-side emulation + * (irregardless of the configuration property 'useServerPrepStmts') + * with the same semantics as the java.sql.Connection.prepareStatement() + * method with the same argument types. * - * @param sql - * DOCUMENT ME! - * @return DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String, int, int, int) */ - public PreparedStatement clientPrepareStatement(String sql) - throws SQLException { - return clientPrepareStatement(sql, - java.sql.ResultSet.TYPE_SCROLL_SENSITIVE, - java.sql.ResultSet.CONCUR_READ_ONLY); - } + public abstract java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException; /** - * @see Connection#prepareStatement(String, int) - */ - public java.sql.PreparedStatement clientPrepareStatement(String sql, - int autoGenKeyIndex) throws SQLException { - java.sql.PreparedStatement pStmt = clientPrepareStatement(sql); - - ((com.mysql.jdbc.PreparedStatement) pStmt) - .setRetrieveGeneratedKeys(autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS); - - return pStmt; - } - - /** - * DOCUMENT ME! + * Prepares a statement on the client, using client-side emulation + * (irregardless of the configuration property 'useServerPrepStmts') + * with the same semantics as the java.sql.Connection.prepareStatement() + * method with the same argument types. * - * @param sql - * DOCUMENT ME! - * @param resultSetType - * DOCUMENT ME! - * @param resultSetConcurrency - * DOCUMENT ME! - * @return DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String, String[]) */ - public PreparedStatement clientPrepareStatement(String sql, - int resultSetType, int resultSetConcurrency) throws SQLException { - return clientPrepareStatement(sql, resultSetType, resultSetConcurrency, true); - } - - protected PreparedStatement clientPrepareStatement(String sql, - int resultSetType, int resultSetConcurrency, - boolean processEscapeCodesIfNeeded) throws SQLException { - checkClosed(); + public abstract java.sql.PreparedStatement clientPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException; - String nativeSql = processEscapeCodesIfNeeded && getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; - - PreparedStatement pStmt = null; - - if (getCachePreparedStatements()) { - synchronized (this.cachedPreparedStatementParams) { - PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams - .get(nativeSql); - - if (pStmtInfo == null) { - pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql, - this.database); - - PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo(); - - if (parseInfo.statementLength < getPreparedStatementCacheSqlLimit()) { - if (this.cachedPreparedStatementParams.size() >= getPreparedStatementCacheSize()) { - Iterator oldestIter = this.cachedPreparedStatementParams - .keySet().iterator(); - long lruTime = Long.MAX_VALUE; - String oldestSql = null; - - while (oldestIter.hasNext()) { - String sqlKey = (String) oldestIter.next(); - PreparedStatement.ParseInfo lruInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams - .get(sqlKey); - - if (lruInfo.lastUsed < lruTime) { - lruTime = lruInfo.lastUsed; - oldestSql = sqlKey; - } - } - - if (oldestSql != null) { - this.cachedPreparedStatementParams - .remove(oldestSql); - } - } - - this.cachedPreparedStatementParams.put(nativeSql, pStmt - .getParseInfo()); - } - } else { - pStmtInfo.lastUsed = System.currentTimeMillis(); - pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql, - this.database, pStmtInfo); - } - } - } else { - pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql, - this.database); - } - - pStmt.setResultSetType(resultSetType); - pStmt.setResultSetConcurrency(resultSetConcurrency); - - return pStmt; - } - - - public void close() throws SQLException { - realClose(true, true, false, null); - } - /** - * Closes all currently open statements. - * - * @throws SQLException - * DOCUMENT ME! + * Returns the number of statements active on this connection, which + * haven't been .close()d. */ - private void closeAllOpenStatements() throws SQLException { - SQLException postponedException = null; + public abstract int getActiveStatementCount(); - if (this.openStatements != null) { - List currentlyOpenStatements = new ArrayList(); // we need this to - // avoid - // ConcurrentModificationEx - - for (Iterator iter = this.openStatements.keySet().iterator(); iter - .hasNext();) { - currentlyOpenStatements.add(iter.next()); - } - - int numStmts = currentlyOpenStatements.size(); - - for (int i = 0; i < numStmts; i++) { - Statement stmt = (Statement) currentlyOpenStatements.get(i); - - try { - stmt.realClose(false, true); - } catch (SQLException sqlEx) { - postponedException = sqlEx; // throw it later, cleanup all - // statements first - } - } - - if (postponedException != null) { - throw postponedException; - } - } - } - - private void closeStatement(java.sql.Statement stmt) { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException sqlEx) { - ; // ignore - } - - stmt = null; - } - } - - // --------------------------JDBC 2.0----------------------------- - /** - * The method commit() makes all changes made since the previous - * commit/rollback permanent and releases any database locks currently held - * by the Connection. This method should only be used when auto-commit has - * been disabled. - *

- * Note: MySQL does not support transactions, so this method is a - * no-op. - *

+ * Reports how long this connection has been idle. + * This time (reported in milliseconds) is updated once a query has + * completed. * - * @exception SQLException - * if a database access error occurs - * @see setAutoCommit - */ - public void commit() throws SQLException { - synchronized (getMutex()) { - checkClosed(); - - try { - // no-op if _relaxAutoCommit == true - if (this.autoCommit && !getRelaxAutoCommit()) { - throw SQLError.createSQLException("Can't call commit when autocommit=true"); - } else if (this.transactionsSupported) { - if (getUseLocalSessionState() && versionMeetsMinimum(5, 0, 0)) { - if (!this.io.inTransactionOnServer()) { - return; // effectively a no-op - } - } - - execSQL(null, "commit", -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, - false); - } - } catch (SQLException sqlException) { - if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE - .equals(sqlException.getSQLState())) { - throw SQLError.createSQLException( - "Communications link failure during commit(). Transaction resolution unknown.", - SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN); - } - - throw sqlException; - } finally { - this.needsPing = this.getReconnectAtTxEnd(); - } - - return; - } - } - - /** - * Configures client-side properties for character set information. - * - * @throws SQLException - * if unable to configure the specified character set. - */ - private void configureCharsetProperties() throws SQLException { - if (getEncoding() != null) { - // Attempt to use the encoding, and bail out if it - // can't be used - try { - String testString = "abc"; - testString.getBytes(getEncoding()); - } catch (UnsupportedEncodingException UE) { - // Try the MySQL character encoding, then.... - String oldEncoding = getEncoding(); - - setEncoding(CharsetMapping.getJavaEncodingForMysqlEncoding( - oldEncoding, this)); - - if (getEncoding() == null) { - throw SQLError.createSQLException( - "Java does not support the MySQL character encoding " - + " " + "encoding '" + oldEncoding + "'.", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - - try { - String testString = "abc"; - testString.getBytes(getEncoding()); - } catch (UnsupportedEncodingException encodingEx) { - throw SQLError.createSQLException("Unsupported character " - + "encoding '" + getEncoding() + "'.", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - } - } - } - - /** - * Sets up client character set for MySQL-4.1 and newer if the user This - * must be done before any further communication with the server! - * - * @return true if this routine actually configured the client character - * set, or false if the driver needs to use 'older' methods to - * detect the character set, as it is connected to a MySQL server - * older than 4.1.0 - * @throws SQLException - * if an exception happens while sending 'SET NAMES' to the - * server, or the server sends character set information that - * the client doesn't know about. - */ - private boolean configureClientCharacterSet() throws SQLException { - String realJavaEncoding = getEncoding(); - boolean characterSetAlreadyConfigured = false; - - try { - if (versionMeetsMinimum(4, 1, 0)) { - characterSetAlreadyConfigured = true; - - setUseUnicode(true); - - configureCharsetProperties(); - realJavaEncoding = getEncoding(); // we need to do this again - // to grab this for - // versions > 4.1.0 - - try { - - // Fault injection for testing server character set indices - - if (props != null && props.getProperty("com.mysql.jdbc.faultInjection.serverCharsetIndex") != null) { - this.io.serverCharsetIndex = Integer.parseInt( - props.getProperty( - "com.mysql.jdbc.faultInjection.serverCharsetIndex")); - } - - String serverEncodingToSet = - CharsetMapping.INDEX_TO_CHARSET[this.io.serverCharsetIndex]; - - if (serverEncodingToSet == null || serverEncodingToSet.length() == 0) { - if (realJavaEncoding != null) { - // user knows best, try it - setEncoding(realJavaEncoding); - } else { - throw SQLError.createSQLException( - "Unknown initial character set index '" - + this.io.serverCharsetIndex - + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.", - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - // "latin1" on MySQL-4.1.0+ is actually CP1252, not ISO8859_1 - if (versionMeetsMinimum(4, 1, 0) && - "ISO8859_1".equalsIgnoreCase(serverEncodingToSet)) { - serverEncodingToSet = "Cp1252"; - } - - setEncoding(serverEncodingToSet); - - } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) { - if (realJavaEncoding != null) { - // user knows best, try it - setEncoding(realJavaEncoding); - } else { - throw SQLError.createSQLException( - "Unknown initial character set index '" - + this.io.serverCharsetIndex - + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.", - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - if (getEncoding() == null) { - // punt? - setEncoding("ISO8859_1"); - } - - // - // Has the user has 'forced' the character encoding via - // driver properties? - // - if (getUseUnicode()) { - if (realJavaEncoding != null) { - - // - // Now, inform the server what character set we - // will be using from now-on... - // - if (realJavaEncoding.equalsIgnoreCase("UTF-8") - || realJavaEncoding.equalsIgnoreCase("UTF8")) { - // charset names are case-sensitive - - if (!getUseOldUTF8Behavior()) { - if (!characterSetNamesMatches("utf8")) { - execSQL(null, "SET NAMES utf8", -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.database, true, false); - } - } - - setEncoding(realJavaEncoding); - } /* not utf-8 */else { - String mysqlEncodingName = CharsetMapping - .getMysqlEncodingForJavaEncoding( - realJavaEncoding - .toUpperCase(Locale.ENGLISH), - this); - - /* - * if ("koi8_ru".equals(mysqlEncodingName)) { // - * This has a _different_ name in 4.1... - * mysqlEncodingName = "ko18r"; } else if - * ("euc_kr".equals(mysqlEncodingName)) { // - * Different name in 4.1 mysqlEncodingName = - * "euckr"; } - */ - - if (mysqlEncodingName != null) { - - if (!characterSetNamesMatches(mysqlEncodingName)) { - execSQL(null, "SET NAMES " + mysqlEncodingName, - -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.database, true, false); - } - } - - // Switch driver's encoding now, since the server - // knows what we're sending... - // - setEncoding(realJavaEncoding); - } - } else if (getEncoding() != null) { - // Tell the server we'll use the server default charset - // to send our - // queries from now on.... - String mysqlEncodingName = CharsetMapping - .getMysqlEncodingForJavaEncoding(getEncoding() - .toUpperCase(Locale.ENGLISH), this); - - if (!characterSetNamesMatches(mysqlEncodingName)) { - execSQL(null, "SET NAMES " + mysqlEncodingName, -1, - null, java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - } - - realJavaEncoding = getEncoding(); - } - - } - - // - // We know how to deal with any charset coming back from - // the database, so tell the server not to do conversion - // if the user hasn't 'forced' a result-set character set - // - - String onServer = null; - boolean isNullOnServer = false; - - if (this.serverVariables != null) { - onServer = (String)this.serverVariables.get("character_set_results"); - - isNullOnServer = onServer == null || "NULL".equalsIgnoreCase(onServer) || onServer.length() == 0; - } - - if (getCharacterSetResults() == null) { - - // - // Only send if needed, if we're caching server variables - // we -have- to send, because we don't know what it was - // before we cached them. - // - if (!isNullOnServer) { - execSQL(null, "SET character_set_results = NULL", -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, - false); - if (!this.usingCachedConfig) { - this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, null); - } - } else { - if (!this.usingCachedConfig) { - this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, onServer); - } - } - } else { - String charsetResults = getCharacterSetResults(); - String mysqlEncodingName = null; - - if ("UTF-8".equalsIgnoreCase(charsetResults) - || "UTF8".equalsIgnoreCase(charsetResults)) { - mysqlEncodingName = "utf8"; - } else { - mysqlEncodingName = CharsetMapping - .getMysqlEncodingForJavaEncoding(charsetResults - .toUpperCase(Locale.ENGLISH), this); - } - - // - // Only change the value if needed - // - - if (!mysqlEncodingName.equalsIgnoreCase( - (String)this.serverVariables.get("character_set_results"))) { - StringBuffer setBuf = new StringBuffer( - "SET character_set_results = ".length() - + mysqlEncodingName.length()); - setBuf.append("SET character_set_results = ").append( - mysqlEncodingName); - - execSQL(null, setBuf.toString(), -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - - if (!this.usingCachedConfig) { - this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, - mysqlEncodingName); - } - } else { - if (!this.usingCachedConfig) { - this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, onServer); - } - } - } - - if (getConnectionCollation() != null) { - StringBuffer setBuf = new StringBuffer( - "SET collation_connection = ".length() - + getConnectionCollation().length()); - setBuf.append("SET collation_connection = ").append( - getConnectionCollation()); - - execSQL(null, setBuf.toString(), -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - } - } else { - // Use what the server has specified - realJavaEncoding = getEncoding(); // so we don't get - // swapped out in the finally - // block.... - } - } finally { - // Failsafe, make sure that the driver's notion of character - // encoding matches what the user has specified. - // - setEncoding(realJavaEncoding); - } - - return characterSetAlreadyConfigured; - } - - private boolean characterSetNamesMatches(String mysqlEncodingName) { - // set names is equivalent to character_set_client ..._results and ..._connection, - // but we set _results later, so don't check it here. - - return (mysqlEncodingName != null && - mysqlEncodingName.equalsIgnoreCase((String)this.serverVariables.get("character_set_client")) && - mysqlEncodingName.equalsIgnoreCase((String)this.serverVariables.get("character_set_connection"))); - } - - /** - * Configures the client's timezone if required. - * - * @throws SQLException - * if the timezone the server is configured to use can't be - * mapped to a Java timezone. - */ - private void configureTimezone() throws SQLException { - String configuredTimeZoneOnServer = (String) this.serverVariables - .get("timezone"); - - if (configuredTimeZoneOnServer == null) { - configuredTimeZoneOnServer = (String) this.serverVariables - .get("time_zone"); - - if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) { - configuredTimeZoneOnServer = (String) this.serverVariables - .get("system_time_zone"); - } - } - - if (getUseTimezone() && configuredTimeZoneOnServer != null) { - // user can specify/override as property - String canoncicalTimezone = getServerTimezone(); - - if ((canoncicalTimezone == null) - || (canoncicalTimezone.length() == 0)) { - String serverTimezoneStr = configuredTimeZoneOnServer; - - try { - canoncicalTimezone = TimeUtil - .getCanoncialTimezone(serverTimezoneStr); - - if (canoncicalTimezone == null) { - throw SQLError.createSQLException("Can't map timezone '" - + serverTimezoneStr + "' to " - + " canonical timezone.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } catch (IllegalArgumentException iae) { - throw SQLError.createSQLException(iae.getMessage(), - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - this.serverTimezoneTZ = TimeZone.getTimeZone(canoncicalTimezone); - - // - // The Calendar class has the behavior of mapping - // unknown timezones to 'GMT' instead of throwing an - // exception, so we must check for this... - // - if (!canoncicalTimezone.equalsIgnoreCase("GMT") - && this.serverTimezoneTZ.getID().equals("GMT")) { - throw SQLError.createSQLException("No timezone mapping entry for '" - + canoncicalTimezone + "'", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - if ("GMT".equalsIgnoreCase(this.serverTimezoneTZ.getID())) { - this.isServerTzUTC = true; - } else { - this.isServerTzUTC = false; - } - } - } - - private void createInitialHistogram(long[] breakpoints, - long lowerBound, long upperBound) { - - double bucketSize = (((double) upperBound - (double) lowerBound) / HISTOGRAM_BUCKETS) * 1.25; - - if (bucketSize < 1) { - bucketSize = 1; - } - - for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { - breakpoints[i] = lowerBound; - lowerBound += bucketSize; - } - } - - /** - * Creates an IO channel to the server - * - * @param isForReconnect - * is this request for a re-connect - * @return a new MysqlIO instance connected to a server - * @throws SQLException - * if a database access error occurs - * @throws CommunicationsException - * DOCUMENT ME! - */ - protected com.mysql.jdbc.MysqlIO createNewIO(boolean isForReconnect) - throws SQLException { - MysqlIO newIo = null; - - Properties mergedProps = new Properties(); - - mergedProps = exposeAsProperties(this.props); - - long queriesIssuedFailedOverCopy = this.queriesIssuedFailedOver; - this.queriesIssuedFailedOver = 0; - - try { - if (!getHighAvailability() && !this.failedOver) { - boolean connectionGood = false; - Exception connectionNotEstablishedBecause = null; - - int hostIndex = 0; - - // - // TODO: Eventually, when there's enough metadata - // on the server to support it, we should come up - // with a smarter way to pick what server to connect - // to...perhaps even making it 'pluggable' - // - if (getRoundRobinLoadBalance()) { - hostIndex = getNextRoundRobinHostIndex(getURL(), - this.hostList); - } - - for (; hostIndex < this.hostListSize; hostIndex++) { - - if (hostIndex == 0) { - this.hasTriedMasterFlag = true; - } - - try { - String newHostPortPair = (String) this.hostList - .get(hostIndex); - - int newPort = 3306; - - String[] hostPortPair = NonRegisteringDriver - .parseHostPortPair(newHostPortPair); - String newHost = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX]; - - if (newHost == null || newHost.trim().length() == 0) { - newHost = "localhost"; - } - - if (hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) { - try { - newPort = Integer - .parseInt(hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]); - } catch (NumberFormatException nfe) { - throw SQLError.createSQLException( - "Illegal connection port value '" - + hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] - + "'", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - } - - this.io = new MysqlIO(newHost, newPort, mergedProps, - getSocketFactoryClassName(), this, - getSocketTimeout()); - - this.io.doHandshake(this.user, this.password, - this.database); - this.connectionId = this.io.getThreadId(); - this.isClosed = false; - - // save state from old connection - boolean oldAutoCommit = getAutoCommit(); - int oldIsolationLevel = this.isolationLevel; - boolean oldReadOnly = isReadOnly(); - String oldCatalog = getCatalog(); - - // Server properties might be different - // from previous connection, so initialize - // again... - initializePropsFromServer(); - - if (isForReconnect) { - // Restore state from old connection - setAutoCommit(oldAutoCommit); - - if (this.hasIsolationLevels) { - setTransactionIsolation(oldIsolationLevel); - } - - setCatalog(oldCatalog); - } - - if (hostIndex != 0) { - setFailedOverState(); - queriesIssuedFailedOverCopy = 0; - } else { - this.failedOver = false; - queriesIssuedFailedOverCopy = 0; - - if (this.hostListSize > 1) { - setReadOnlyInternal(false); - } else { - setReadOnlyInternal(oldReadOnly); - } - } - - connectionGood = true; - - break; // low-level connection succeeded - } catch (Exception EEE) { - if (this.io != null) { - this.io.forceClose(); - } - - connectionNotEstablishedBecause = EEE; - - connectionGood = false; - - if (EEE instanceof SQLException) { - SQLException sqlEx = (SQLException)EEE; - - String sqlState = sqlEx.getSQLState(); - - // If this isn't a communications failure, it will probably never succeed, so - // give up right here and now .... - if ((sqlState == null) - || !sqlState - .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) { - throw sqlEx; - } - } - - // Check next host, it might be up... - if (getRoundRobinLoadBalance()) { - hostIndex = getNextRoundRobinHostIndex(getURL(), - this.hostList) - 1 /* incremented by for loop next time around */; - } else if ((this.hostListSize - 1) == hostIndex) { - throw new CommunicationsException(this, - (this.io != null) ? this.io - .getLastPacketSentTimeMs() : 0, - EEE); - } - } - } - - if (!connectionGood) { - // We've really failed! - throw SQLError.createSQLException( - "Could not create connection to database server due to underlying exception: '" - + connectionNotEstablishedBecause - + "'." - + (getParanoid() ? "" - : Util - .stackTraceToString(connectionNotEstablishedBecause)), - SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); - } - } else { - double timeout = getInitialTimeout(); - boolean connectionGood = false; - - Exception connectionException = null; - - int hostIndex = 0; - - if (getRoundRobinLoadBalance()) { - hostIndex = getNextRoundRobinHostIndex(getURL(), - this.hostList); - } - - for (; (hostIndex < this.hostListSize) && !connectionGood; hostIndex++) { - if (hostIndex == 0) { - this.hasTriedMasterFlag = true; - } - - if (this.preferSlaveDuringFailover && hostIndex == 0) { - hostIndex++; - } - - for (int attemptCount = 0; (attemptCount < getMaxReconnects()) - && !connectionGood; attemptCount++) { - try { - if (this.io != null) { - this.io.forceClose(); - } - - String newHostPortPair = (String) this.hostList - .get(hostIndex); - - int newPort = 3306; - - String[] hostPortPair = NonRegisteringDriver - .parseHostPortPair(newHostPortPair); - String newHost = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX]; - - if (newHost == null || newHost.trim().length() == 0) { - newHost = "localhost"; - } - - if (hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) { - try { - newPort = Integer - .parseInt(hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]); - } catch (NumberFormatException nfe) { - throw SQLError.createSQLException( - "Illegal connection port value '" - + hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] - + "'", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - } - - this.io = new MysqlIO(newHost, newPort, - mergedProps, getSocketFactoryClassName(), - this, getSocketTimeout()); - this.io.doHandshake(this.user, this.password, - this.database); - - pingInternal(false); - this.connectionId = this.io.getThreadId(); - this.isClosed = false; - - // save state from old connection - boolean oldAutoCommit = getAutoCommit(); - int oldIsolationLevel = this.isolationLevel; - boolean oldReadOnly = isReadOnly(); - String oldCatalog = getCatalog(); - - // Server properties might be different - // from previous connection, so initialize - // again... - initializePropsFromServer(); - - if (isForReconnect) { - // Restore state from old connection - setAutoCommit(oldAutoCommit); - - if (this.hasIsolationLevels) { - setTransactionIsolation(oldIsolationLevel); - } - - setCatalog(oldCatalog); - } - - connectionGood = true; - - if (hostIndex != 0) { - setFailedOverState(); - queriesIssuedFailedOverCopy = 0; - } else { - this.failedOver = false; - queriesIssuedFailedOverCopy = 0; - - if (this.hostListSize > 1) { - setReadOnlyInternal(false); - } else { - setReadOnlyInternal(oldReadOnly); - } - } - - break; - } catch (Exception EEE) { - connectionException = EEE; - connectionGood = false; - - // Check next host, it might be up... - if (getRoundRobinLoadBalance()) { - hostIndex = getNextRoundRobinHostIndex(getURL(), - this.hostList) - 1 /* incremented by for loop next time around */; - } - } - - if (connectionGood) { - break; - } - - if (attemptCount > 0) { - try { - Thread.sleep((long) timeout * 1000); - } catch (InterruptedException IE) { - ; - } - } - } // end attempts for a single host - } // end iterator for list of hosts - - if (!connectionGood) { - // We've really failed! - throw SQLError.createSQLException( - "Server connection failure during transaction. Due to underlying exception: '" - + connectionException - + "'." - + (getParanoid() ? "" - : Util - .stackTraceToString(connectionException)) - + "\nAttempted reconnect " - + getMaxReconnects() + " times. Giving up.", - SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); - } - } - - if (getParanoid() && !getHighAvailability() - && (this.hostListSize <= 1)) { - this.password = null; - this.user = null; - } - - if (isForReconnect) { - // - // Retrieve any 'lost' prepared statements if re-connecting - // - Iterator statementIter = this.openStatements.values() - .iterator(); - - // - // We build a list of these outside the map of open statements, - // because - // in the process of re-preparing, we might end up having to - // close - // a prepared statement, thus removing it from the map, and - // generating - // a ConcurrentModificationException - // - Stack serverPreparedStatements = null; - - while (statementIter.hasNext()) { - Object statementObj = statementIter.next(); - - if (statementObj instanceof ServerPreparedStatement) { - if (serverPreparedStatements == null) { - serverPreparedStatements = new Stack(); - } - - serverPreparedStatements.add(statementObj); - } - } - - if (serverPreparedStatements != null) { - while (!serverPreparedStatements.isEmpty()) { - ((ServerPreparedStatement) serverPreparedStatements - .pop()).rePrepare(); - } - } - } - - return newIo; - } finally { - this.queriesIssuedFailedOver = queriesIssuedFailedOverCopy; - } - } - - private void createPreparedStatementCaches() { - int cacheSize = getPreparedStatementCacheSize(); - - this.cachedPreparedStatementParams = new HashMap(cacheSize); - - this.serverSideStatementCheckCache = new LRUCache(cacheSize); - - this.serverSideStatementCache = new LRUCache(cacheSize) { - protected boolean removeEldestEntry(java.util.Map.Entry eldest) { - if (this.maxElements <= 1) { - return false; - } - - boolean removeIt = super.removeEldestEntry(eldest); - - if (removeIt) { - ServerPreparedStatement ps = - (ServerPreparedStatement)eldest.getValue(); - ps.isCached = false; - ps.setClosed(false); - - try { - ps.close(); - } catch (SQLException sqlEx) { - // punt - } - } - - return removeIt; - } - }; - } - - /** - * SQL statements without parameters are normally executed using Statement - * objects. If the same SQL statement is executed many times, it is more - * efficient to use a PreparedStatement - * - * @return a new Statement object - * @throws SQLException - * passed through from the constructor - */ - public java.sql.Statement createStatement() throws SQLException { - return createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY); - } - - /** - * JDBC 2.0 Same as createStatement() above, but allows the default result - * set type and result set concurrency type to be overridden. - * - * @param resultSetType - * a result set type, see ResultSet.TYPE_XXX - * @param resultSetConcurrency - * a concurrency type, see ResultSet.CONCUR_XXX - * @return a new Statement object - * @exception SQLException - * if a database-access error occurs. - */ - public java.sql.Statement createStatement(int resultSetType, - int resultSetConcurrency) throws SQLException { - checkClosed(); - - Statement stmt = new com.mysql.jdbc.Statement(this, this.database); - stmt.setResultSetType(resultSetType); - stmt.setResultSetConcurrency(resultSetConcurrency); - - return stmt; - } - - /** - * @see Connection#createStatement(int, int, int) - */ - public java.sql.Statement createStatement(int resultSetType, - int resultSetConcurrency, int resultSetHoldability) - throws SQLException { - if (getPedantic()) { - if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { - throw SQLError.createSQLException( - "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } - - return createStatement(resultSetType, resultSetConcurrency); - } - - protected void dumpTestcaseQuery(String query) { - System.err.println(query); - } - - protected Connection duplicate() throws SQLException { - return new Connection( this.origHostToConnectTo, - this.origPortToConnectTo, - this.props, - this.origDatabaseToConnectTo, - this.myURL); - } - - /** - * Send a query to the server. Returns one of the ResultSet objects. This is - * synchronized, so Statement's queries will be serialized. - * - * @param callingStatement - * DOCUMENT ME! - * @param sql - * the SQL statement to be executed - * @param maxRows - * DOCUMENT ME! - * @param packet - * DOCUMENT ME! - * @param resultSetType - * DOCUMENT ME! - * @param resultSetConcurrency - * DOCUMENT ME! - * @param streamResults - * DOCUMENT ME! - * @param queryIsSelectOnly - * DOCUMENT ME! - * @param catalog - * DOCUMENT ME! - * @param unpackFields - * DOCUMENT ME! - * @return a ResultSet holding the results - * @exception SQLException - * if a database error occurs - */ - - // ResultSet execSQL(Statement callingStatement, String sql, - // int maxRowsToRetreive, String catalog) throws SQLException { - // return execSQL(callingStatement, sql, maxRowsToRetreive, null, - // java.sql.ResultSet.TYPE_FORWARD_ONLY, - // java.sql.ResultSet.CONCUR_READ_ONLY, catalog); - // } - // ResultSet execSQL(Statement callingStatement, String sql, int maxRows, - // int resultSetType, int resultSetConcurrency, boolean streamResults, - // boolean queryIsSelectOnly, String catalog, boolean unpackFields) throws - // SQLException { - // return execSQL(callingStatement, sql, maxRows, null, resultSetType, - // resultSetConcurrency, streamResults, queryIsSelectOnly, catalog, - // unpackFields); - // } - ResultSet execSQL(Statement callingStatement, String sql, int maxRows, - Buffer packet, int resultSetType, int resultSetConcurrency, - boolean streamResults, String catalog, - boolean unpackFields) throws SQLException { - return execSQL(callingStatement, sql, maxRows, packet, resultSetType, - resultSetConcurrency, streamResults, - catalog, unpackFields, false); - } - - ResultSet execSQL(Statement callingStatement, String sql, int maxRows, - Buffer packet, int resultSetType, int resultSetConcurrency, - boolean streamResults, String catalog, - boolean unpackFields, - boolean isBatch) throws SQLException { - // - // Fall-back if the master is back online if we've - // issued queriesBeforeRetryMaster queries since - // we failed over - // - synchronized (this.mutex) { - long queryStartTime = 0; - - int endOfQueryPacketPosition = 0; - - if (packet != null) { - endOfQueryPacketPosition = packet.getPosition(); - } - - if (getGatherPerformanceMetrics()) { - queryStartTime = System.currentTimeMillis(); - } - - this.lastQueryFinishedTime = 0; // we're busy! - - if (this.failedOver && this.autoCommit && !isBatch) { - if (shouldFallBack() && !this.executingFailoverReconnect) { - try { - this.executingFailoverReconnect = true; - - createNewIO(true); - - String connectedHost = this.io.getHost(); - - if ((connectedHost != null) - && this.hostList.get(0).equals(connectedHost)) { - this.failedOver = false; - this.queriesIssuedFailedOver = 0; - setReadOnlyInternal(false); - } - } finally { - this.executingFailoverReconnect = false; - } - } - } - - if ((getHighAvailability() || this.failedOver) - && (this.autoCommit || getAutoReconnectForPools()) - && this.needsPing && !isBatch) { - try { - pingInternal(false); - - this.needsPing = false; - } catch (Exception Ex) { - createNewIO(true); - } - } - - try { - if (packet == null) { - String encoding = null; - - if (getUseUnicode()) { - encoding = getEncoding(); - } - - return this.io.sqlQueryDirect(callingStatement, sql, - encoding, null, maxRows, this, resultSetType, - resultSetConcurrency, streamResults, catalog, - unpackFields); - } - - return this.io.sqlQueryDirect(callingStatement, null, null, - packet, maxRows, this, resultSetType, - resultSetConcurrency, streamResults, catalog, - unpackFields); - } catch (java.sql.SQLException sqlE) { - // don't clobber SQL exceptions - - if (getDumpQueriesOnException()) { - String extractedSql = extractSqlFromPacket(sql, packet, - endOfQueryPacketPosition); - StringBuffer messageBuf = new StringBuffer(extractedSql - .length() + 32); - messageBuf - .append("\n\nQuery being executed when exception was thrown:\n\n"); - messageBuf.append(extractedSql); - - sqlE = appendMessageToException(sqlE, messageBuf.toString()); - } - - if ((getHighAvailability() || this.failedOver)) { - this.needsPing = true; - } else { - String sqlState = sqlE.getSQLState(); - - if ((sqlState != null) - && sqlState - .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) { - cleanup(sqlE); - } - } - - throw sqlE; - } catch (Exception ex) { - if ((getHighAvailability() || this.failedOver)) { - this.needsPing = true; - } else if (ex instanceof IOException) { - cleanup(ex); - } - - String exceptionType = ex.getClass().getName(); - String exceptionMessage = ex.getMessage(); - - if (!getParanoid()) { - exceptionMessage += "\n\nNested Stack Trace:\n"; - exceptionMessage += Util.stackTraceToString(ex); - } - - throw new java.sql.SQLException( - "Error during query: Unexpected Exception: " - + exceptionType + " message given: " - + exceptionMessage, - SQLError.SQL_STATE_GENERAL_ERROR); - } finally { - if (getMaintainTimeStats()) { - this.lastQueryFinishedTime = System.currentTimeMillis(); - } - - if (this.failedOver) { - this.queriesIssuedFailedOver++; - } - - if (getGatherPerformanceMetrics()) { - long queryTime = System.currentTimeMillis() - - queryStartTime; - - registerQueryExecutionTime(queryTime); - } - } - } - } - - protected String extractSqlFromPacket(String possibleSqlQuery, - Buffer queryPacket, int endOfQueryPacketPosition) - throws SQLException { - - String extractedSql = null; - - if (possibleSqlQuery != null) { - if (possibleSqlQuery.length() > getMaxQuerySizeToLog()) { - StringBuffer truncatedQueryBuf = new StringBuffer( - possibleSqlQuery.substring(0, getMaxQuerySizeToLog())); - truncatedQueryBuf.append(Messages.getString("MysqlIO.25")); - extractedSql = truncatedQueryBuf.toString(); - } else { - extractedSql = possibleSqlQuery; - } - } - - if (extractedSql == null) { - // This is probably from a client-side prepared - // statement - - int extractPosition = endOfQueryPacketPosition; - - boolean truncated = false; - - if (endOfQueryPacketPosition > getMaxQuerySizeToLog()) { - extractPosition = getMaxQuerySizeToLog(); - truncated = true; - } - - extractedSql = new String(queryPacket.getByteBuffer(), 5, - (extractPosition - 5)); - - if (truncated) { - extractedSql += Messages.getString("MysqlIO.25"); //$NON-NLS-1$ - } - } - - return extractedSql; - - } - - /** - * DOCUMENT ME! - * - * @throws Throwable - * DOCUMENT ME! - */ - protected void finalize() throws Throwable { - cleanup(null); - } - - protected StringBuffer generateConnectionCommentBlock(StringBuffer buf) { - buf.append("/* conn id "); - buf.append(getId()); - buf.append(" */ "); - - return buf; - } - - public int getActiveStatementCount() { - // Might not have one of these if - // not tracking open resources - if (this.openStatements != null) { - synchronized (this.openStatements) { - return this.openStatements.size(); - } - } - - return 0; - } - - /** - * Gets the current auto-commit state - * - * @return Current state of auto-commit - * @exception SQLException - * if an error occurs - * @see setAutoCommit - */ - public boolean getAutoCommit() throws SQLException { - return this.autoCommit; - } - - /** - * Optimization to only use one calendar per-session, or calculate it for - * each call, depending on user configuration - */ - protected Calendar getCalendarInstanceForSessionOrNew() { - if (getDynamicCalendars()) { - return Calendar.getInstance(); - } - - return getSessionLockedCalendar(); - } - - /** - * Return the connections current catalog name, or null if no catalog name - * is set, or we dont support catalogs. - *

- * Note: MySQL's notion of catalogs are individual databases. - *

- * - * @return the current catalog name or null - * @exception SQLException - * if a database access error occurs - */ - public String getCatalog() throws SQLException { - return this.database; - } - - /** - * @return Returns the characterSetMetadata. - */ - protected String getCharacterSetMetadata() { - return characterSetMetadata; - } - - /** - * Returns the locally mapped instance of a charset converter (to avoid - * overhead of static synchronization). - * - * @param javaEncodingName - * the encoding name to retrieve - * @return a character converter, or null if one couldn't be mapped. - */ - SingleByteCharsetConverter getCharsetConverter( - String javaEncodingName) throws SQLException { - if (javaEncodingName == null) { - return null; - } - - if (this.usePlatformCharsetConverters) { - return null; // we'll use Java's built-in routines for this - // they're finally fast enough - } - - SingleByteCharsetConverter converter = null; - - synchronized (this.charsetConverterMap) { - Object asObject = this.charsetConverterMap - .get(javaEncodingName); - - if (asObject == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) { - return null; - } - - converter = (SingleByteCharsetConverter)asObject; - - if (converter == null) { - try { - converter = SingleByteCharsetConverter.getInstance( - javaEncodingName, this); - - if (converter == null) { - this.charsetConverterMap.put(javaEncodingName, - CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); - } else { - this.charsetConverterMap.put(javaEncodingName, converter); - } - } catch (UnsupportedEncodingException unsupEncEx) { - this.charsetConverterMap.put(javaEncodingName, - CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); - - converter = null; - } - } - } - - return converter; - } - - /** - * Returns the Java character encoding name for the given MySQL server - * charset index - * - * @param charsetIndex - * @return the Java character encoding name for the given MySQL server - * charset index - * @throws SQLException - * if the character set index isn't known by the driver - */ - protected String getCharsetNameForIndex(int charsetIndex) - throws SQLException { - String charsetName = null; - - if (getUseOldUTF8Behavior()) { - return getEncoding(); - } - - if (charsetIndex != MysqlDefs.NO_CHARSET_INFO) { - try { - charsetName = this.indexToCharsetMapping[charsetIndex]; - - if ("sjis".equalsIgnoreCase(charsetName) || - "MS932".equalsIgnoreCase(charsetName) /* for JDK6 */) { - // Use our encoding so that code pages like Cp932 work - if (CharsetMapping.isAliasForSjis(getEncoding())) { - charsetName = getEncoding(); - } - } - } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) { - throw SQLError.createSQLException( - "Unknown character set index for field '" - + charsetIndex + "' received from server.", - SQLError.SQL_STATE_GENERAL_ERROR); - } - - // Punt - if (charsetName == null) { - charsetName = getEncoding(); - } - } else { - charsetName = getEncoding(); - } - - return charsetName; - } - - /** - * DOCUMENT ME! - * - * @return Returns the defaultTimeZone. - */ - protected TimeZone getDefaultTimeZone() { - return this.defaultTimeZone; - } - - /** - * @see Connection#getHoldability() - */ - public int getHoldability() throws SQLException { - return java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; - } - - long getId() { - return this.connectionId; - } - - /** - * NOT JDBC-Compliant, but clients can use this method to determine how long - * this connection has been idle. This time (reported in milliseconds) is - * updated once a query has completed. - * * @return number of ms that this connection has been idle, 0 if the driver * is busy retrieving results. */ - public long getIdleFor() { - if (this.lastQueryFinishedTime == 0) { - return 0; - } + public abstract long getIdleFor(); - long now = System.currentTimeMillis(); - long idleTime = now - this.lastQueryFinishedTime; - - return idleTime; - } - /** - * Returns the IO channel to the server - * - * @return the IO channel to the server - * @throws SQLException - * if the connection is closed. - */ - protected MysqlIO getIO() throws SQLException { - if ((this.io == null) || this.isClosed) { - throw SQLError.createSQLException( - "Operation not allowed on closed connection", - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); - } - - return this.io; - } - - /** * Returns the log mechanism that should be used to log information from/for * this Connection. * * @return the Log instance to use for logging messages. * @throws SQLException * if an error occurs */ - public Log getLog() throws SQLException { - return this.log; - } + public abstract Log getLog() throws SQLException; /** - * Returns the maximum packet size the MySQL server will accept - * - * @return DOCUMENT ME! - */ - int getMaxAllowedPacket() { - return this.maxAllowedPacket; - } - - protected int getMaxBytesPerChar(String javaCharsetName) - throws SQLException { - // TODO: Check if we can actually run this query at this point in time - String charset = CharsetMapping.getMysqlEncodingForJavaEncoding( - javaCharsetName, this); - - if (versionMeetsMinimum(4, 1, 0)) { - Map mapToCheck = null; - - if (!getUseDynamicCharsetInfo()) { - mapToCheck = CharsetMapping.STATIC_CHARSET_TO_NUM_BYTES_MAP; - } else { - mapToCheck = this.charsetToNumBytesMap; - - synchronized (this.charsetToNumBytesMap) { - if (this.charsetToNumBytesMap.isEmpty()) { - - java.sql.Statement stmt = null; - java.sql.ResultSet rs = null; - - try { - stmt = getMetadataSafeStatement(); - - rs = stmt.executeQuery("SHOW CHARACTER SET"); - - while (rs.next()) { - this.charsetToNumBytesMap.put(rs.getString("Charset"), - new Integer(rs.getInt("Maxlen"))); - } - - rs.close(); - rs = null; - - stmt.close(); - - stmt = null; - } finally { - if (rs != null) { - rs.close(); - rs = null; - } - - if (stmt != null) { - stmt.close(); - stmt = null; - } - } - } - } - } - - Integer mbPerChar = (Integer) mapToCheck.get(charset); - - if (mbPerChar != null) { - return mbPerChar.intValue(); - } - - return 1; // we don't know - } - - return 1; // we don't know - } - - /** - * A connection's database is able to provide information describing its - * tables, its supported SQL grammar, its stored procedures, the - * capabilities of this connection, etc. This information is made available - * through a DatabaseMetaData object. - * - * @return a DatabaseMetaData object for this connection - * @exception SQLException - * if a database access error occurs - */ - public java.sql.DatabaseMetaData getMetaData() throws SQLException { - checkClosed(); - - if (getUseInformationSchema() && - this.versionMeetsMinimum(5, 0, 7)) { - return new DatabaseMetaDataUsingInfoSchema(this, this.database); - } - - return new DatabaseMetaData(this, this.database); - } - - protected java.sql.Statement getMetadataSafeStatement() throws SQLException { - java.sql.Statement stmt = createStatement(); - - if (stmt.getMaxRows() != 0) { - stmt.setMaxRows(0); - } - - stmt.setEscapeProcessing(false); - - return stmt; - } - - /** - * Returns the Mutex all queries are locked against - * - * @return DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - */ - Object getMutex() throws SQLException { - if (this.io == null) { - throw SQLError.createSQLException( - "Connection.close() has already been called. Invalid operation in this state.", - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); - } - - reportMetricsIfNeeded(); - - return this.mutex; - } - - /** - * Returns the packet buffer size the MySQL server reported upon connection - * - * @return DOCUMENT ME! - */ - int getNetBufferLength() { - return this.netBufferLength; - } - - /** * Returns the server's character set * * @return the server's character set. */ - protected String getServerCharacterEncoding() { - if (this.io.versionMeetsMinimum(4, 1, 0)) { - return (String) this.serverVariables.get("character_set_server"); - } else { - return (String) this.serverVariables.get("character_set"); - } - } + public abstract String getServerCharacterEncoding(); - int getServerMajorVersion() { - return this.io.getServerMajorVersion(); - } - - int getServerMinorVersion() { - return this.io.getServerMinorVersion(); - } - - int getServerSubMinorVersion() { - return this.io.getServerSubMinorVersion(); - } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * Returns the TimeZone that represents the configured + * timezone for the server. */ - public TimeZone getServerTimezoneTZ() { - return this.serverTimezoneTZ; - } + public abstract TimeZone getServerTimezoneTZ(); - String getServerVariable(String variableName) { - if (this.serverVariables != null) { - return (String) this.serverVariables.get(variableName); - } - - return null; - } - - String getServerVersion() { - return this.io.getServerVersion(); - } - - protected Calendar getSessionLockedCalendar() { - - return this.sessionCalendar; - } - - /** - * Get this Connection's current transaction isolation mode. + * Returns the comment that will be prepended to all statements + * sent to the server. * - * @return the current TRANSACTION_ mode value - * @exception SQLException - * if a database access error occurs + * @return the comment that will be prepended to all statements + * sent to the server. */ - public int getTransactionIsolation() throws SQLException { + public abstract String getStatementComment(); - if (this.hasIsolationLevels && !getUseLocalSessionState()) { - java.sql.Statement stmt = null; - java.sql.ResultSet rs = null; - - try { - stmt = getMetadataSafeStatement(); - - String query = null; - - int offset = 0; - - if (versionMeetsMinimum(4, 0, 3)) { - query = "SELECT @@session.tx_isolation"; - offset = 1; - } else { - query = "SHOW VARIABLES LIKE 'transaction_isolation'"; - offset = 2; - } - - rs = stmt.executeQuery(query); - - if (rs.next()) { - String s = rs.getString(offset); - - if (s != null) { - Integer intTI = (Integer) mapTransIsolationNameToValue - .get(s); - - if (intTI != null) { - return intTI.intValue(); - } - } - - throw SQLError.createSQLException( - "Could not map transaction isolation '" + s - + " to a valid JDBC level.", - SQLError.SQL_STATE_GENERAL_ERROR); - } - - throw SQLError.createSQLException( - "Could not retrieve transaction isolation level from server", - SQLError.SQL_STATE_GENERAL_ERROR); - - } finally { - if (rs != null) { - try { - rs.close(); - } catch (Exception ex) { - // ignore - ; - } - - rs = null; - } - - if (stmt != null) { - try { - stmt.close(); - } catch (Exception ex) { - // ignore - ; - } - - stmt = null; - } - } - } - - return this.isolationLevel; - } - /** - * JDBC 2.0 Get the type-map object associated with this connection. By - * default, the map returned is empty. - * - * @return the type map - * @throws SQLException - * if a database error occurs + * Has this connection tried to execute a query on the "master" + * server (first host in a multiple host list). */ - public synchronized java.util.Map getTypeMap() throws SQLException { - if (this.typeMap == null) { - this.typeMap = new HashMap(); - } + public abstract boolean hasTriedMaster(); - return this.typeMap; - } - - String getURL() { - return this.myURL; - } - - String getUser() { - return this.user; - } - - protected Calendar getUtcCalendar() { - return this.utcCalendar; - } - /** - * The first warning reported by calls on this Connection is returned. - * Note: Sebsequent warnings will be changed to this - * java.sql.SQLWarning - * - * @return the first java.sql.SQLWarning or null - * @exception SQLException - * if a database access error occurs + * Is this connection currently a participant in an XA transaction? */ - public SQLWarning getWarnings() throws SQLException { - return null; - } - - public boolean hasSameProperties(Connection c) { - return this.props.equals(c.props); - } - - protected void incrementNumberOfPreparedExecutes() { - if (getGatherPerformanceMetrics()) { - this.numberOfPreparedExecutes++; - - // We need to increment this, because - // server-side prepared statements bypass - // any execution by the connection itself... - this.numberOfQueriesIssued++; - } - } + public abstract boolean isInGlobalTx(); - protected void incrementNumberOfPrepares() { - if (getGatherPerformanceMetrics()) { - this.numberOfPrepares++; - } - } - - protected void incrementNumberOfResultSetsCreated() { - if (getGatherPerformanceMetrics()) { - this.numberOfResultSetsCreated++; - } - } - /** - * Initializes driver properties that come from URL or properties passed to - * the driver manager. - * - * @param info - * DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! + * Set the state of being in a global (XA) transaction. + * @param flag */ - private void initializeDriverProperties(Properties info) - throws SQLException { - initializeProperties(info); - - this.usePlatformCharsetConverters = getUseJvmCharsetConverters(); + public void setInGlobalTx(boolean flag); - this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME); - - if (getProfileSql() || getUseUsageAdvisor()) { - this.eventSink = ProfileEventSink.getInstance(this); - } - - if (getCachePreparedStatements()) { - createPreparedStatementCaches(); - } - - if (getNoDatetimeStringSync() && getUseTimezone()) { - throw SQLError.createSQLException( - "Can't enable noDatetimeSync and useTimezone configuration " - + "properties at the same time", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - - if (getCacheCallableStatements()) { - this.parsedCallableStatementCache = new LRUCache( - getCallableStatementCacheSize()); - } - - if (getAllowMultiQueries()) { - setCacheResultSetMetadata(false); // we don't handle this yet - } - - if (getCacheResultSetMetadata()) { - this.resultSetMetadataCache = new LRUCache( - getMetadataCacheSize()); - } - } - /** - * Sets varying properties that depend on server information. Called once we - * have connected to the server. - * - * @param info - * DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - */ - private void initializePropsFromServer() throws SQLException { - setSessionVariables(); - - // - // the "boolean" type didn't come along until MySQL-4.1 - // - - if (!versionMeetsMinimum(4, 1, 0)) { - setTransformedBitIsBoolean(false); - } - - this.parserKnowsUnicode = versionMeetsMinimum(4, 1, 0); - - // - // Users can turn off detection of server-side prepared statements - // - if (getUseServerPreparedStmts() && versionMeetsMinimum(4, 1, 0)) { - this.useServerPreparedStmts = true; - - if (versionMeetsMinimum(5, 0, 0) && !versionMeetsMinimum(5, 0, 3)) { - this.useServerPreparedStmts = false; // 4.1.2+ style prepared - // statements - // don't work on these versions - } - } - - this.serverVariables.clear(); - - // - // If version is greater than 3.21.22 get the server - // variables. - if (versionMeetsMinimum(3, 21, 22)) { - loadServerVariables(); - - buildCollationMapping(); - - LicenseConfiguration.checkLicenseType(this.serverVariables); - - String lowerCaseTables = (String) this.serverVariables - .get("lower_case_table_names"); - - this.lowerCaseTableNames = "on".equalsIgnoreCase(lowerCaseTables) - || "1".equalsIgnoreCase(lowerCaseTables) - || "2".equalsIgnoreCase(lowerCaseTables); - - configureTimezone(); - - if (this.serverVariables.containsKey("max_allowed_packet")) { - this.maxAllowedPacket = getServerVariableAsInt("max_allowed_packet", 1024 * 1024); - - int preferredBlobSendChunkSize = getBlobSendChunkSize(); - - int allowedBlobSendChunkSize = Math.min(preferredBlobSendChunkSize, - this.maxAllowedPacket) - - ServerPreparedStatement.BLOB_STREAM_READ_BUF_SIZE - - 11 /* LONG_DATA and MySQLIO packet header size */; - - setBlobSendChunkSize(String.valueOf(allowedBlobSendChunkSize)); - } - - if (this.serverVariables.containsKey("net_buffer_length")) { - this.netBufferLength = getServerVariableAsInt("net_buffer_length", 16 * 1024); - } - - checkTransactionIsolationLevel(); - - if (!versionMeetsMinimum(4, 1, 0)) { - checkServerEncoding(); - } - - this.io.checkForCharsetMismatch(); - - if (this.serverVariables.containsKey("sql_mode")) { - int sqlMode = 0; - - String sqlModeAsString = (String) this.serverVariables - .get("sql_mode"); - try { - sqlMode = Integer.parseInt(sqlModeAsString); - } catch (NumberFormatException nfe) { - // newer versions of the server has this as a string-y - // list... - sqlMode = 0; - - if (sqlModeAsString != null) { - if (sqlModeAsString.indexOf("ANSI_QUOTES") != -1) { - sqlMode |= 4; - } - - if (sqlModeAsString.indexOf("NO_BACKSLASH_ESCAPES") != -1) { - this.noBackslashEscapes = true; - } - } - } - - if ((sqlMode & 4) > 0) { - this.useAnsiQuotes = true; - } else { - this.useAnsiQuotes = false; - } - } - } - - this.errorMessageEncoding = - CharsetMapping.getCharacterEncodingForErrorMessages(this); - - - boolean overrideDefaultAutocommit = isAutoCommitNonDefaultOnServer(); - - configureClientCharacterSet(); - - if (versionMeetsMinimum(3, 23, 15)) { - this.transactionsSupported = true; - - if (!overrideDefaultAutocommit) { - setAutoCommit(true); // to override anything - // the server is set to...reqd - // by JDBC spec. - } - } else { - this.transactionsSupported = false; - } - - - if (versionMeetsMinimum(3, 23, 36)) { - this.hasIsolationLevels = true; - } else { - this.hasIsolationLevels = false; - } - - this.hasQuotedIdentifiers = versionMeetsMinimum(3, 23, 6); - - this.io.resetMaxBuf(); - - // - // If we're using MySQL 4.1.0 or newer, we need to figure - // out what character set metadata will be returned in, - // and then map that to a Java encoding name. - // - // We've already set it, and it might be different than what - // was originally on the server, which is why we use the - // "special" key to retrieve it - if (this.io.versionMeetsMinimum(4, 1, 0)) { - String characterSetResultsOnServerMysql = (String) this.serverVariables - .get(JDBC_LOCAL_CHARACTER_SET_RESULTS); - - if (characterSetResultsOnServerMysql == null - || StringUtils.startsWithIgnoreCaseAndWs( - characterSetResultsOnServerMysql, "NULL") - || characterSetResultsOnServerMysql.length() == 0) { - String defaultMetadataCharsetMysql = (String) this.serverVariables - .get("character_set_system"); - String defaultMetadataCharset = null; - - if (defaultMetadataCharsetMysql != null) { - defaultMetadataCharset = CharsetMapping - .getJavaEncodingForMysqlEncoding( - defaultMetadataCharsetMysql, this); - } else { - defaultMetadataCharset = "UTF-8"; - } - - this.characterSetMetadata = defaultMetadataCharset; - } else { - this.characterSetResultsOnServer = CharsetMapping - .getJavaEncodingForMysqlEncoding( - characterSetResultsOnServerMysql, this); - this.characterSetMetadata = this.characterSetResultsOnServer; - } - } - - // - // Query cache is broken wrt. multi-statements before MySQL-4.1.10 - // - - if (this.versionMeetsMinimum(4, 1, 0) - && !this.versionMeetsMinimum(4, 1, 10) - && getAllowMultiQueries()) { - if ("ON".equalsIgnoreCase((String) this.serverVariables - .get("query_cache_type")) - && !"0".equalsIgnoreCase((String) this.serverVariables - .get("query_cache_size"))) { - setAllowMultiQueries(false); - } - } - - // - // Server can do this more efficiently for us - // - - setupServerForTruncationChecks(); - } - - private int getServerVariableAsInt(String variableName, int fallbackValue) - throws SQLException { - try { - return Integer.parseInt((String) this.serverVariables - .get(variableName)); - } catch (NumberFormatException nfe) { - getLog().logWarn(Messages.getString("Connection.BadValueInServerVariables", new Object[] {variableName, - this.serverVariables.get(variableName), new Integer(fallbackValue)})); - - return fallbackValue; - } - } - - /** - * Has the default autocommit value of 0 been changed on the server - * via init_connect? - * - * @return true if autocommit is not the default of '0' on the server. - * - * @throws SQLException - */ - private boolean isAutoCommitNonDefaultOnServer() throws SQLException { - boolean overrideDefaultAutocommit = false; - - String initConnectValue = (String) this.serverVariables - .get("init_connect"); - - if (versionMeetsMinimum(4, 1, 2) && initConnectValue != null - && initConnectValue.length() > 0) { - if (!getElideSetAutoCommits()) { - // auto-commit might have changed - java.sql.ResultSet rs = null; - java.sql.Statement stmt = null; - - try { - stmt = getMetadataSafeStatement(); - - rs = stmt.executeQuery("SELECT @@session.autocommit"); - - if (rs.next()) { - this.autoCommit = rs.getBoolean(1); - if (this.autoCommit != true) { - overrideDefaultAutocommit = true; - } - } - - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException sqlEx) { - // do nothing - } - } - - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException sqlEx) { - // do nothing - } - } - } - } else { - if (this.getIO().isSetNeededForAutoCommitMode(true)) { - // we're not in standard autocommit=true mode - this.autoCommit = false; - overrideDefaultAutocommit = true; - } - } - } - - return overrideDefaultAutocommit; - } - - private void setupServerForTruncationChecks() throws SQLException { - if (getJdbcCompliantTruncation()) { - if (versionMeetsMinimum(5, 0, 2)) { - - String currentSqlMode = - (String)this.serverVariables.get("sql_mode"); - - boolean strictTransTablesIsSet = StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") != -1; - - if (currentSqlMode == null || - currentSqlMode.length() == 0 || !strictTransTablesIsSet) { - StringBuffer commandBuf = new StringBuffer("SET sql_mode='"); - - if (currentSqlMode != null && currentSqlMode.length() > 0) { - commandBuf.append(currentSqlMode); - commandBuf.append(","); - } - - commandBuf.append("STRICT_TRANS_TABLES'"); - - execSQL(null, commandBuf.toString(), -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - - setJdbcCompliantTruncation(false); // server's handling this for us now - } else if (strictTransTablesIsSet) { - // We didn't set it, but someone did, so we piggy back on it - setJdbcCompliantTruncation(false); // server's handling this for us now - } - - } - } - } - - protected boolean isClientTzUTC() { - return this.isClientTzUTC; - } - - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean isClosed() { - return this.isClosed; - } - - protected boolean isCursorFetchEnabled() throws SQLException { - return (versionMeetsMinimum(5, 0, 2) && getUseCursorFetch()); - } - - public boolean isInGlobalTx() { - return this.isInGlobalTx; - } - - /** * Is this connection connected to the first host in the list if * there is a list of servers in the URL? * * @return true if this connection is connected to the first in * the list. */ - public synchronized boolean isMasterConnection() { - return !this.failedOver; - } + public abstract boolean isMasterConnection(); /** * Is the server in a sql_mode that doesn't allow us to use \\ to escape * things? * * @return Returns the noBackslashEscapes. */ - public boolean isNoBackslashEscapesSet() { - return this.noBackslashEscapes; - } + public abstract boolean isNoBackslashEscapesSet(); - boolean isReadInfoMsgEnabled() { - return this.readInfoMsg; - } - /** - * Tests to see if the connection is in Read Only Mode. Note that we cannot - * really put the database in read only mode, but we pretend we can by - * returning the value of the readOnly flag + * Does this connection have the same resource name as the given + * connection (for XA)? * - * @return true if the connection is read only - * @exception SQLException - * if a database access error occurs + * @param c + * @return */ - public boolean isReadOnly() throws SQLException { - return this.readOnly; - } - - protected boolean isRunningOnJDK13() { - return this.isRunningOnJDK13; - } - - public synchronized boolean isSameResource(Connection otherConnection) { - if (otherConnection == null) { - return false; - } - - boolean directCompare = true; - - String otherHost = otherConnection.origHostToConnectTo; - String otherOrigDatabase = otherConnection.origDatabaseToConnectTo; - String otherCurrentCatalog = otherConnection.database; - - if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) { - directCompare = false; - } else if (otherHost != null && otherHost.indexOf(",") == -1 && - otherHost.indexOf(":") == -1) { - // need to check port numbers - directCompare = (otherConnection.origPortToConnectTo == - this.origPortToConnectTo); - } - - if (directCompare) { - if (!nullSafeCompare(otherOrigDatabase, this.origDatabaseToConnectTo)) { directCompare = false; - directCompare = false; - } else if (!nullSafeCompare(otherCurrentCatalog, this.database)) { - directCompare = false; - } - } - - if (directCompare) { - return true; - } - - // Has the user explicitly set a resourceId? - String otherResourceId = otherConnection.getResourceId(); - String myResourceId = getResourceId(); - - if (otherResourceId != null || myResourceId != null) { - directCompare = nullSafeCompare(otherResourceId, myResourceId); - - if (directCompare) { - return true; - } - } - - return false; - } - - protected boolean isServerTzUTC() { - return this.isServerTzUTC; - } - - private boolean usingCachedConfig = false; + public abstract boolean isSameResource(Connection c); /** - * Loads the result of 'SHOW VARIABLES' into the serverVariables field so - * that the driver can configure itself. - * - * @throws SQLException - * if the 'SHOW VARIABLES' query fails for any reason. - */ - private void loadServerVariables() throws SQLException { - - if (getCacheServerConfiguration()) { - synchronized (serverConfigByUrl) { - Map cachedVariableMap = (Map) serverConfigByUrl.get(getURL()); - - if (cachedVariableMap != null) { - this.serverVariables = cachedVariableMap; - this.usingCachedConfig = true; - - return; - } - } - } - - com.mysql.jdbc.Statement stmt = null; - com.mysql.jdbc.ResultSet results = null; - - try { - stmt = (com.mysql.jdbc.Statement) createStatement(); - stmt.setEscapeProcessing(false); - - results = (com.mysql.jdbc.ResultSet) stmt - .executeQuery("SHOW SESSION VARIABLES"); - - while (results.next()) { - this.serverVariables.put(results.getString(1), results - .getString(2)); - } - - if (getCacheServerConfiguration()) { - synchronized (serverConfigByUrl) { - serverConfigByUrl.put(getURL(), this.serverVariables); - } - } - } catch (SQLException e) { - throw e; - } finally { - if (results != null) { - try { - results.close(); - } catch (SQLException sqlE) { - ; - } - } - - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException sqlE) { - ; - } - } - } - } - - /** * Is the server configured to use lower-case table names only? * * @return true if lower_case_table_names is 'on' */ - public boolean lowerCaseTableNames() { - return this.lowerCaseTableNames; - } + public abstract boolean lowerCaseTableNames(); /** - * Has the maxRows value changed? - * - * @param stmt - * DOCUMENT ME! + * Does the server this connection is connected to + * support unicode? */ - void maxRowsChanged(Statement stmt) { - synchronized (this.mutex) { - if (this.statementsUsingMaxRows == null) { - this.statementsUsingMaxRows = new HashMap(); - } + public abstract boolean parserKnowsUnicode(); - this.statementsUsingMaxRows.put(stmt, stmt); - - this.maxRowsChanged = true; - } - } - /** - * A driver may convert the JDBC sql grammar into its system's native SQL - * grammar prior to sending it; nativeSQL returns the native form of the - * statement that the driver would have sent. + * Detect if the connection is still good by sending a ping command + * to the server. * - * @param sql - * a SQL statement that may contain one or more '?' parameter - * placeholders - * @return the native form of this statement - * @exception SQLException - * if a database access error occurs - */ - public String nativeSQL(String sql) throws SQLException { - if (sql == null) { - return null; - } - - Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, - serverSupportsConvertFn(), - this); - - if (escapedSqlResult instanceof String) { - return (String) escapedSqlResult; - } - - return ((EscapeProcessorResult) escapedSqlResult).escapedSql; - } - - private CallableStatement parseCallableStatement(String sql) - throws SQLException { - Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, - serverSupportsConvertFn(), this); - - boolean isFunctionCall = false; - String parsedSql = null; - - if (escapedSqlResult instanceof EscapeProcessorResult) { - parsedSql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; - isFunctionCall = ((EscapeProcessorResult) escapedSqlResult).callingStoredFunction; - } else { - parsedSql = (String) escapedSqlResult; - isFunctionCall = false; - } - - return new CallableStatement(this, parsedSql, this.database, - isFunctionCall); - } - - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean parserKnowsUnicode() { - return this.parserKnowsUnicode; - } - - /** - * Detect if the connection is still good - * * @throws SQLException * if the ping fails */ - public void ping() throws SQLException { - pingInternal(true); - } + public abstract void ping() throws SQLException; - private void pingInternal(boolean checkForClosedConnection) - throws SQLException { - if (checkForClosedConnection) { - checkClosed(); - } - - // Need MySQL-3.22.1, but who uses anything older!? - this.io.sendCommand(MysqlDefs.PING, null, null, false, null); - } - /** - * DOCUMENT ME! - * - * @param sql - * DOCUMENT ME! - * @return DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - */ - public java.sql.CallableStatement prepareCall(String sql) - throws SQLException { - if (this.getUseUltraDevWorkAround()) { - return new UltraDevWorkAround(prepareStatement(sql)); - } - - return prepareCall(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY); - } - - /** - * JDBC 2.0 Same as prepareCall() above, but allows the default result set - * type and result set concurrency type to be overridden. - * - * @param sql - * the SQL representing the callable statement - * @param resultSetType - * a result set type, see ResultSet.TYPE_XXX - * @param resultSetConcurrency - * a concurrency type, see ResultSet.CONCUR_XXX - * @return a new CallableStatement object containing the pre-compiled SQL - * statement - * @exception SQLException - * if a database-access error occurs. - */ - public java.sql.CallableStatement prepareCall(String sql, - int resultSetType, int resultSetConcurrency) throws SQLException { - if (versionMeetsMinimum(5, 0, 0)) { - CallableStatement cStmt = null; - - if (!getCacheCallableStatements()) { - - cStmt = parseCallableStatement(sql); - } else { - synchronized (this.parsedCallableStatementCache) { - CompoundCacheKey key = new CompoundCacheKey(getCatalog(), sql); - - CallableStatement.CallableStatementParamInfo cachedParamInfo = (CallableStatement.CallableStatementParamInfo) this.parsedCallableStatementCache - .get(key); - - if (cachedParamInfo != null) { - cStmt = new CallableStatement(this, cachedParamInfo); - } else { - cStmt = parseCallableStatement(sql); - - cachedParamInfo = cStmt.paramInfo; - - this.parsedCallableStatementCache.put(key, cachedParamInfo); - } - } - } - - cStmt.setResultSetType(resultSetType); - cStmt.setResultSetConcurrency(resultSetConcurrency); - - return cStmt; - } - - throw SQLError.createSQLException("Callable statements not " + "supported.", - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); - } - - /** - * @see Connection#prepareCall(String, int, int, int) - */ - public java.sql.CallableStatement prepareCall(String sql, - int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - if (getPedantic()) { - if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { - throw SQLError.createSQLException( - "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } - - CallableStatement cStmt = (com.mysql.jdbc.CallableStatement) prepareCall( - sql, resultSetType, resultSetConcurrency); - - return cStmt; - } - - /** - * A SQL statement with or without IN parameters can be pre-compiled and - * stored in a PreparedStatement object. This object can then be used to - * efficiently execute this statement multiple times. - *

- * Note: This method is optimized for handling parametric SQL - * statements that benefit from precompilation if the driver supports - * precompilation. In this case, the statement is not sent to the database - * until the PreparedStatement is executed. This has no direct effect on - * users; however it does affect which method throws certain - * java.sql.SQLExceptions - *

- *

- * MySQL does not support precompilation of statements, so they are handled - * by the driver. - *

- * - * @param sql - * a SQL statement that may contain one or more '?' IN parameter - * placeholders - * @return a new PreparedStatement object containing the pre-compiled - * statement. - * @exception SQLException - * if a database access error occurs. - */ - public java.sql.PreparedStatement prepareStatement(String sql) - throws SQLException { - return prepareStatement(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY); - } - - /** - * @see Connection#prepareStatement(String, int) - */ - public java.sql.PreparedStatement prepareStatement(String sql, - int autoGenKeyIndex) throws SQLException { - java.sql.PreparedStatement pStmt = prepareStatement(sql); - - ((com.mysql.jdbc.PreparedStatement) pStmt) - .setRetrieveGeneratedKeys(autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS); - - return pStmt; - } - - /** - * JDBC 2.0 Same as prepareStatement() above, but allows the default result - * set type and result set concurrency type to be overridden. - * - * @param sql - * the SQL query containing place holders - * @param resultSetType - * a result set type, see ResultSet.TYPE_XXX - * @param resultSetConcurrency - * a concurrency type, see ResultSet.CONCUR_XXX - * @return a new PreparedStatement object containing the pre-compiled SQL - * statement - * @exception SQLException - * if a database-access error occurs. - */ - public java.sql.PreparedStatement prepareStatement(String sql, - int resultSetType, int resultSetConcurrency) throws SQLException { - checkClosed(); - - // - // FIXME: Create warnings if can't create results of the given - // type or concurrency - // - PreparedStatement pStmt = null; - - boolean canServerPrepare = true; - - String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; - - if (getEmulateUnsupportedPstmts()) { - canServerPrepare = canHandleAsServerPreparedStatement(nativeSql); - } - - if (this.useServerPreparedStmts && canServerPrepare) { - if (this.getCachePreparedStatements()) { - synchronized (this.serverSideStatementCache) { - pStmt = (com.mysql.jdbc.ServerPreparedStatement)this.serverSideStatementCache.remove(sql); - - if (pStmt != null) { - ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false); - pStmt.clearParameters(); - } - - if (pStmt == null) { - try { - pStmt = new com.mysql.jdbc.ServerPreparedStatement(this, nativeSql, - this.database, resultSetType, resultSetConcurrency); - if (sql.length() < getPreparedStatementCacheSqlLimit()) { - ((com.mysql.jdbc.ServerPreparedStatement)pStmt).isCached = true; - } - } catch (SQLException sqlEx) { - // Punt, if necessary - if (getEmulateUnsupportedPstmts()) { - pStmt = clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); - - if (sql.length() < getPreparedStatementCacheSqlLimit()) { - this.serverSideStatementCheckCache.put(sql, Boolean.FALSE); - } - } else { - throw sqlEx; - } - } - } - } - } else { - try { - pStmt = new com.mysql.jdbc.ServerPreparedStatement(this, nativeSql, - this.database, resultSetType, resultSetConcurrency); - } catch (SQLException sqlEx) { - // Punt, if necessary - if (getEmulateUnsupportedPstmts()) { - pStmt = clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); - } else { - throw sqlEx; - } - } - } - } else { - pStmt = clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); - } - - return pStmt; - } - - /** - * @see Connection#prepareStatement(String, int, int, int) - */ - public java.sql.PreparedStatement prepareStatement(String sql, - int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - if (getPedantic()) { - if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { - throw SQLError.createSQLException( - "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } - - return prepareStatement(sql, resultSetType, resultSetConcurrency); - } - - /** - * @see Connection#prepareStatement(String, int[]) - */ - public java.sql.PreparedStatement prepareStatement(String sql, - int[] autoGenKeyIndexes) throws SQLException { - java.sql.PreparedStatement pStmt = prepareStatement(sql); - - ((com.mysql.jdbc.PreparedStatement) pStmt) - .setRetrieveGeneratedKeys((autoGenKeyIndexes != null) - && (autoGenKeyIndexes.length > 0)); - - return pStmt; - } - - /** - * @see Connection#prepareStatement(String, String[]) - */ - public java.sql.PreparedStatement prepareStatement(String sql, - String[] autoGenKeyColNames) throws SQLException { - java.sql.PreparedStatement pStmt = prepareStatement(sql); - - ((com.mysql.jdbc.PreparedStatement) pStmt) - .setRetrieveGeneratedKeys((autoGenKeyColNames != null) - && (autoGenKeyColNames.length > 0)); - - return pStmt; - } - - /** - * Closes connection and frees resources. - * - * @param calledExplicitly - * is this being called from close() - * @param issueRollback - * should a rollback() be issued? - * @throws SQLException - * if an error occurs - */ - protected void realClose(boolean calledExplicitly, boolean issueRollback, - boolean skipLocalTeardown, Throwable reason) throws SQLException { - SQLException sqlEx = null; - - if (this.isClosed()) { - return; - } - - this.forceClosedReason = reason; - - try { - if (!skipLocalTeardown) { - if (!getAutoCommit() && issueRollback) { - try { - rollback(); - } catch (SQLException ex) { - sqlEx = ex; - } - } - - reportMetrics(); - - if (getUseUsageAdvisor()) { - if (!calledExplicitly) { - String message = "Connection implicitly closed by Driver. You should call Connection.close() from your code to free resources more efficiently and avoid resource leaks."; - - this.eventSink.consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$ - this.getCatalog(), this.getId(), -1, -1, System - .currentTimeMillis(), 0, Constants.MILLIS_I18N, - null, - this.pointOfOrigin, message)); - } - - long connectionLifeTime = System.currentTimeMillis() - - this.connectionCreationTimeMillis; - - if (connectionLifeTime < 500) { - String message = "Connection lifetime of < .5 seconds. You might be un-necessarily creating short-lived connections and should investigate connection pooling to be more efficient."; - - this.eventSink.consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$ - this.getCatalog(), this.getId(), -1, -1, System - .currentTimeMillis(), 0, Constants.MILLIS_I18N, - null, - this.pointOfOrigin, message)); - } - } - - try { - closeAllOpenStatements(); - } catch (SQLException ex) { - sqlEx = ex; - } - - if (this.io != null) { - try { - this.io.quit(); - } catch (Exception e) { - ; - } - - } - } else { - this.io.forceClose(); - } - } finally { - this.openStatements = null; - this.io = null; - ProfileEventSink.removeInstance(this); - this.isClosed = true; - } - - if (sqlEx != null) { - throw sqlEx; - } - - } - - protected void recachePreparedStatement(ServerPreparedStatement pstmt) { - synchronized (this.serverSideStatementCache) { - this.serverSideStatementCache.put(pstmt.originalSql, pstmt); - } - } - - /** - * DOCUMENT ME! - * - * @param queryTimeMs - */ - protected void registerQueryExecutionTime(long queryTimeMs) { - if (queryTimeMs > this.longestQueryTimeMs) { - this.longestQueryTimeMs = queryTimeMs; - - repartitionPerformanceHistogram(); - } - - addToPerformanceHistogram(queryTimeMs, 1); - - if (queryTimeMs < this.shortestQueryTimeMs) { - this.shortestQueryTimeMs = (queryTimeMs == 0) ? 1 : queryTimeMs; - } - - this.numberOfQueriesIssued++; - - this.totalQueryTimeMs += queryTimeMs; - } - - /** - * Register a Statement instance as open. - * - * @param stmt - * the Statement instance to remove - */ - void registerStatement(Statement stmt) { - synchronized (this.openStatements) { - this.openStatements.put(stmt, stmt); - } - } - - /** - * @see Connection#releaseSavepoint(Savepoint) - */ - public void releaseSavepoint(Savepoint arg0) throws SQLException { - // this is a no-op - } - - private void repartitionHistogram(int[] histCounts, long[] histBreakpoints, - long currentLowerBound, long currentUpperBound) { - - if (oldHistCounts == null) { - oldHistCounts = new int[histCounts.length]; - oldHistBreakpoints = new long[histBreakpoints.length]; - } - - for (int i = 0; i < histCounts.length; i++) { - oldHistCounts[i] = histCounts[i]; - } - - for (int i = 0; i < oldHistBreakpoints.length; i++) { - oldHistBreakpoints[i] = histBreakpoints[i]; - } - - createInitialHistogram(histBreakpoints, currentLowerBound, - currentUpperBound); - - for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { - addToHistogram(histCounts, histBreakpoints, oldHistBreakpoints[i], - oldHistCounts[i], currentLowerBound, currentUpperBound); - } - } - - private void repartitionPerformanceHistogram() { - checkAndCreatePerformanceHistogram(); - - repartitionHistogram(this.perfMetricsHistCounts, - this.perfMetricsHistBreakpoints, - this.shortestQueryTimeMs == Long.MAX_VALUE ? 0 - : this.shortestQueryTimeMs, this.longestQueryTimeMs); - } - - private void repartitionTablesAccessedHistogram() { - checkAndCreateTablesAccessedHistogram(); - - repartitionHistogram(this.numTablesMetricsHistCounts, - this.numTablesMetricsHistBreakpoints, - this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0 - : this.minimumNumberTablesAccessed, - this.maximumNumberTablesAccessed); - } - - private void reportMetrics() { - if (getGatherPerformanceMetrics()) { - StringBuffer logMessage = new StringBuffer(256); - - logMessage.append("** Performance Metrics Report **\n"); - logMessage.append("\nLongest reported query: " - + this.longestQueryTimeMs + " ms"); - logMessage.append("\nShortest reported query: " - + this.shortestQueryTimeMs + " ms"); - logMessage - .append("\nAverage query execution time: " - + (this.totalQueryTimeMs / this.numberOfQueriesIssued) - + " ms"); - logMessage.append("\nNumber of statements executed: " - + this.numberOfQueriesIssued); - logMessage.append("\nNumber of result sets created: " - + this.numberOfResultSetsCreated); - logMessage.append("\nNumber of statements prepared: " - + this.numberOfPrepares); - logMessage.append("\nNumber of prepared statement executions: " - + this.numberOfPreparedExecutes); - - if (this.perfMetricsHistBreakpoints != null) { - logMessage.append("\n\n\tTiming Histogram:\n"); - int maxNumPoints = 20; - int highestCount = Integer.MIN_VALUE; - - for (int i = 0; i < (HISTOGRAM_BUCKETS); i++) { - if (this.perfMetricsHistCounts[i] > highestCount) { - highestCount = this.perfMetricsHistCounts[i]; - } - } - - if (highestCount == 0) { - highestCount = 1; // avoid DIV/0 - } - - for (int i = 0; i < (HISTOGRAM_BUCKETS - 1); i++) { - - if (i == 0) { - logMessage.append("\n\tless than " - + this.perfMetricsHistBreakpoints[i + 1] - + " ms: \t" + this.perfMetricsHistCounts[i]); - } else { - logMessage.append("\n\tbetween " - + this.perfMetricsHistBreakpoints[i] + " and " - + this.perfMetricsHistBreakpoints[i + 1] - + " ms: \t" + this.perfMetricsHistCounts[i]); - } - - logMessage.append("\t"); - - int numPointsToGraph = (int) (maxNumPoints * ((double) this.perfMetricsHistCounts[i] / (double) highestCount)); - - for (int j = 0; j < numPointsToGraph; j++) { - logMessage.append("*"); - } - - if (this.longestQueryTimeMs < this.perfMetricsHistCounts[i + 1]) { - break; - } - } - - if (this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2] < this.longestQueryTimeMs) { - logMessage.append("\n\tbetween "); - logMessage - .append(this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2]); - logMessage.append(" and "); - logMessage - .append(this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 1]); - logMessage.append(" ms: \t"); - logMessage - .append(this.perfMetricsHistCounts[HISTOGRAM_BUCKETS - 1]); - } - } - - if (this.numTablesMetricsHistBreakpoints != null) { - logMessage.append("\n\n\tTable Join Histogram:\n"); - int maxNumPoints = 20; - int highestCount = Integer.MIN_VALUE; - - for (int i = 0; i < (HISTOGRAM_BUCKETS); i++) { - if (this.numTablesMetricsHistCounts[i] > highestCount) { - highestCount = this.numTablesMetricsHistCounts[i]; - } - } - - if (highestCount == 0) { - highestCount = 1; // avoid DIV/0 - } - - for (int i = 0; i < (HISTOGRAM_BUCKETS - 1); i++) { - - if (i == 0) { - logMessage.append("\n\t" - + this.numTablesMetricsHistBreakpoints[i + 1] - + " tables or less: \t\t" - + this.numTablesMetricsHistCounts[i]); - } else { - logMessage.append("\n\tbetween " - + this.numTablesMetricsHistBreakpoints[i] - + " and " - + this.numTablesMetricsHistBreakpoints[i + 1] - + " tables: \t" - + this.numTablesMetricsHistCounts[i]); - } - - logMessage.append("\t"); - - int numPointsToGraph = (int) (maxNumPoints * ((double) this.numTablesMetricsHistCounts[i] / (double) highestCount)); - - for (int j = 0; j < numPointsToGraph; j++) { - logMessage.append("*"); - } - - if (this.maximumNumberTablesAccessed < this.numTablesMetricsHistBreakpoints[i + 1]) { - break; - } - } - - if (this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2] < this.maximumNumberTablesAccessed) { - logMessage.append("\n\tbetween "); - logMessage - .append(this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2]); - logMessage.append(" and "); - logMessage - .append(this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 1]); - logMessage.append(" tables: "); - logMessage - .append(this.numTablesMetricsHistCounts[HISTOGRAM_BUCKETS - 1]); - } - } - - this.log.logInfo(logMessage); - - this.metricsLastReportedMs = System.currentTimeMillis(); - } - } - - /** - * Reports currently collected metrics if this feature is enabled and the - * timeout has passed. - */ - private void reportMetricsIfNeeded() { - if (getGatherPerformanceMetrics()) { - if ((System.currentTimeMillis() - this.metricsLastReportedMs) > getReportMetricsIntervalMillis()) { - reportMetrics(); - } - } - } - - protected void reportNumberOfTablesAccessed(int numTablesAccessed) { - if (numTablesAccessed < this.minimumNumberTablesAccessed) { - this.minimumNumberTablesAccessed = numTablesAccessed; - } - - if (numTablesAccessed > this.maximumNumberTablesAccessed) { - this.maximumNumberTablesAccessed = numTablesAccessed; - - repartitionTablesAccessedHistogram(); - } - - addToTablesAccessedHistogram(numTablesAccessed, 1); - } - - /** * Resets the server-side state of this connection. Doesn't work for MySQL * versions older than 4.0.6 or if isParanoid() is set (it will become a * no-op in these cases). Usually only used from connection pooling code. * * @throws SQLException * if the operation fails while resetting server state. */ - public void resetServerState() throws SQLException { - if (!getParanoid() - && ((this.io != null) && versionMeetsMinimum(4, 0, 6))) { - changeUser(this.user, this.password); - } - } + public abstract void resetServerState() throws SQLException; /** - * The method rollback() drops all changes made since the previous - * commit/rollback and releases any database locks currently held by the - * Connection. + * Prepares a statement on the server (irregardless of the + * configuration property 'useServerPrepStmts') with the same semantics + * as the java.sql.Connection.prepareStatement() method with the + * same argument types. * - * @exception SQLException - * if a database access error occurs - * @see commit + * @see java.sql.Connection#prepareStatement(String) */ - public void rollback() throws SQLException { - synchronized (getMutex()) { - checkClosed(); - - try { - // no-op if _relaxAutoCommit == true - if (this.autoCommit && !getRelaxAutoCommit()) { - throw SQLError.createSQLException( - "Can't call rollback when autocommit=true", - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); - } else if (this.transactionsSupported) { - try { - rollbackNoChecks(); - } catch (SQLException sqlEx) { - // We ignore non-transactional tables if told to do so - if (getIgnoreNonTxTables() - && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) { - throw sqlEx; - } - } - } - } catch (SQLException sqlException) { - if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE - .equals(sqlException.getSQLState())) { - throw SQLError.createSQLException( - "Communications link failure during rollback(). Transaction resolution unknown.", - SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN); - } - - throw sqlException; - } finally { - this.needsPing = this.getReconnectAtTxEnd(); - } - } - } + public abstract java.sql.PreparedStatement serverPrepareStatement(String sql) + throws SQLException; /** - * @see Connection#rollback(Savepoint) + * Prepares a statement on the server (irregardless of the + * configuration property 'useServerPrepStmts') with the same semantics + * as the java.sql.Connection.prepareStatement() method with the + * same argument types. + * + * @see java.sql.Connection#prepareStatement(String, int) */ - public void rollback(Savepoint savepoint) throws SQLException { + public abstract java.sql.PreparedStatement serverPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException; - if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) { - synchronized (getMutex()) { - checkClosed(); - - try { - StringBuffer rollbackQuery = new StringBuffer( - "ROLLBACK TO SAVEPOINT "); - rollbackQuery.append('`'); - rollbackQuery.append(savepoint.getSavepointName()); - rollbackQuery.append('`'); - - java.sql.Statement stmt = null; - - try { - stmt = createStatement(); - - stmt.executeUpdate(rollbackQuery.toString()); - } catch (SQLException sqlEx) { - int errno = sqlEx.getErrorCode(); - - if (errno == 1181) { - String msg = sqlEx.getMessage(); - - if (msg != null) { - int indexOfError153 = msg.indexOf("153"); - - if (indexOfError153 != -1) { - throw SQLError.createSQLException("Savepoint '" - + savepoint.getSavepointName() - + "' does not exist", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT, - errno); - } - } - } - - // We ignore non-transactional tables if told to do so - if (getIgnoreNonTxTables() - && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) { - throw sqlEx; - } - - if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE - .equals(sqlEx.getSQLState())) { - throw SQLError.createSQLException( - "Communications link failure during rollback(). Transaction resolution unknown.", - SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN); - } - - throw sqlEx; - } finally { - closeStatement(stmt); - } - } finally { - this.needsPing = this.getReconnectAtTxEnd(); - } - } - } else { - throw new NotImplemented(); - } - } - - private void rollbackNoChecks() throws SQLException { - if (getUseLocalSessionState() && versionMeetsMinimum(5, 0, 0)) { - if (!this.io.inTransactionOnServer()) { - return; // effectively a no-op - } - } - - execSQL(null, "rollback", -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - } - /** - * DOCUMENT ME! + * Prepares a statement on the server (irregardless of the + * configuration property 'useServerPrepStmts') with the same semantics + * as the java.sql.Connection.prepareStatement() method with the + * same argument types. * - * @param sql - * DOCUMENT ME! - * @return DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String, int, int) */ - public ServerPreparedStatement serverPrepare(String sql) - throws SQLException { - - String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; - - return new ServerPreparedStatement(this, nativeSql, this.getCatalog(), - java.sql.ResultSet.TYPE_SCROLL_SENSITIVE, - java.sql.ResultSet.CONCUR_READ_ONLY); - } - - protected boolean serverSupportsConvertFn() throws SQLException { - return versionMeetsMinimum(4, 0, 2); - } - + public abstract java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException; /** - * If a connection is in auto-commit mode, than all its SQL statements will - * be executed and committed as individual transactions. Otherwise, its SQL - * statements are grouped into transactions that are terminated by either - * commit() or rollback(). By default, new connections are in auto- commit - * mode. The commit occurs when the statement completes or the next execute - * occurs, whichever comes first. In the case of statements returning a - * ResultSet, the statement completes when the last row of the ResultSet has - * been retrieved or the ResultSet has been closed. In advanced cases, a - * single statement may return multiple results as well as output parameter - * values. Here the commit occurs when all results and output param values - * have been retrieved. - *

- * Note: MySQL does not support transactions, so this method is a - * no-op. - *

+ * Prepares a statement on the server (irregardless of the + * configuration property 'useServerPrepStmts') with the same semantics + * as the java.sql.Connection.prepareStatement() method with the + * same argument types. * - * @param autoCommitFlag - - * true enables auto-commit; false disables it - * @exception SQLException - * if a database access error occurs + * @see java.sql.Connection#prepareStatement(String, int, int, int) */ - public void setAutoCommit(boolean autoCommitFlag) throws SQLException { - synchronized (getMutex()) { - checkClosed(); + public abstract java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException; - if (getAutoReconnectForPools()) { - setHighAvailability(true); - } - - try { - if (this.transactionsSupported) { - - boolean needsSetOnServer = true; - - if (this.getUseLocalSessionState() - && this.autoCommit == autoCommitFlag) { - needsSetOnServer = false; - } else if (!this.getHighAvailability()) { - needsSetOnServer = this.getIO() - .isSetNeededForAutoCommitMode(autoCommitFlag); - } - - // this internal value must be set first as failover depends on - // it - // being set to true to fail over (which is done by most - // app servers and connection pools at the end of - // a transaction), and the driver issues an implicit set - // based on this value when it (re)-connects to a server - // so the value holds across connections - this.autoCommit = autoCommitFlag; - - if (needsSetOnServer) { - execSQL(null, autoCommitFlag ? "SET autocommit=1" - : "SET autocommit=0", -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - } - - } else { - if ((autoCommitFlag == false) && !getRelaxAutoCommit()) { - throw SQLError.createSQLException("MySQL Versions Older than 3.23.15 " - + "do not support transactions", - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); - } - - this.autoCommit = autoCommitFlag; - } - } finally { - if (this.getAutoReconnectForPools()) { - setHighAvailability(false); - } - } - - return; - } - } - /** - * A sub-space of this Connection's database may be selected by setting a - * catalog name. If the driver does not support catalogs, it will silently - * ignore this request - *

- * Note: MySQL's notion of catalogs are individual databases. - *

+ * Prepares a statement on the server (irregardless of the + * configuration property 'useServerPrepStmts') with the same semantics + * as the java.sql.Connection.prepareStatement() method with the + * same argument types. * - * @param catalog - * the database for this connection to use - * @throws SQLException - * if a database access error occurs + * @see java.sql.Connection#prepareStatement(String, int[]) */ - public void setCatalog(String catalog) throws SQLException { - synchronized (getMutex()) { - checkClosed(); + public abstract java.sql.PreparedStatement serverPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException; - if (catalog == null) { - throw SQLError.createSQLException("Catalog can not be null", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - if (getUseLocalSessionState()) { - if (this.lowerCaseTableNames) { - if (this.database.equalsIgnoreCase(catalog)) { - return; - } - } else { - if (this.database.equals(catalog)) { - return; - } - } - } - - String quotedId = this.dbmd.getIdentifierQuoteString(); - - if ((quotedId == null) || quotedId.equals(" ")) { - quotedId = ""; - } - - StringBuffer query = new StringBuffer("USE "); - query.append(quotedId); - query.append(catalog); - query.append(quotedId); - - execSQL(null, query.toString(), -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); - - this.database = catalog; - } - } - /** - * @param failedOver - * The failedOver to set. - */ - public synchronized void setFailedOver(boolean flag) { - this.failedOver = flag; - } - - /** - * Sets state for a failed-over connection + * Prepares a statement on the server (irregardless of the + * configuration property 'useServerPrepStmts') with the same semantics + * as the java.sql.Connection.prepareStatement() method with the + * same argument types. * - * @throws SQLException - * DOCUMENT ME! + * @see java.sql.Connection#prepareStatement(String, String[]) */ - private void setFailedOverState() throws SQLException { - if (getFailOverReadOnly()) { - setReadOnlyInternal(true); - } + public abstract java.sql.PreparedStatement serverPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException; - this.queriesIssuedFailedOver = 0; - this.failedOver = true; - this.masterFailTimeMillis = System.currentTimeMillis(); - } - /** - * @see Connection#setHoldability(int) + * @param failedOver + * The failedOver to set. */ - public void setHoldability(int arg0) throws SQLException { - // do nothing - } + public abstract void setFailedOver(boolean flag); - public void setInGlobalTx(boolean flag) { - this.isInGlobalTx = flag; - } - - // exposed for testing /** * @param preferSlaveDuringFailover * The preferSlaveDuringFailover to set. */ - public void setPreferSlaveDuringFailover(boolean flag) { - this.preferSlaveDuringFailover = flag; - } + public abstract void setPreferSlaveDuringFailover(boolean flag); - void setReadInfoMsgEnabled(boolean flag) { - this.readInfoMsg = flag; - } - /** - * You can put a connection in read-only mode as a hint to enable database - * optimizations Note: setReadOnly cannot be called while in the - * middle of a transaction + * Sets the comment that will be prepended to all statements + * sent to the server. Do not use slash-star or star-slash tokens + * in the comment as these will be added by the driver itself. * - * @param readOnlyFlag - - * true enables read-only mode; false disables it - * @exception SQLException - * if a database access error occurs + * @param comment the comment that will be prepended to all statements + * sent to the server. */ - public void setReadOnly(boolean readOnlyFlag) throws SQLException { - checkClosed(); - - // Ignore calls to this method if we're failed over and - // we're configured to fail over read-only. - if (this.failedOver && getFailOverReadOnly() && !readOnlyFlag) { - return; - } - - setReadOnlyInternal(readOnlyFlag); - } - - protected void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException { - this.readOnly = readOnlyFlag; - } + public abstract void setStatementComment(String comment); /** - * @see Connection#setSavepoint() + * Used by MiniAdmin to shutdown a MySQL server + * + * @throws SQLException + * if the command can not be issued. */ - public java.sql.Savepoint setSavepoint() throws SQLException { - MysqlSavepoint savepoint = new MysqlSavepoint(); + public abstract void shutdownServer() throws SQLException; - setSavepoint(savepoint); - - return savepoint; - } - - private void setSavepoint(MysqlSavepoint savepoint) throws SQLException { - - if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) { - synchronized (getMutex()) { - checkClosed(); - - StringBuffer savePointQuery = new StringBuffer("SAVEPOINT "); - savePointQuery.append('`'); - savePointQuery.append(savepoint.getSavepointName()); - savePointQuery.append('`'); - - java.sql.Statement stmt = null; - - try { - stmt = createStatement(); - - stmt.executeUpdate(savePointQuery.toString()); - } finally { - closeStatement(stmt); - } - } - } else { - throw new NotImplemented(); - } - } - /** - * @see Connection#setSavepoint(String) + * Does the server this connection is connected to + * support quoted isolation levels? */ - public synchronized java.sql.Savepoint setSavepoint(String name) throws SQLException { - MysqlSavepoint savepoint = new MysqlSavepoint(name); + public abstract boolean supportsIsolationLevel(); - setSavepoint(savepoint); - - return savepoint; - } - /** - * + * Does the server this connection is connected to + * support quoted identifiers? */ - private void setSessionVariables() throws SQLException { - if (this.versionMeetsMinimum(4, 0, 0) && getSessionVariables() != null) { - List variablesToSet = StringUtils.split(getSessionVariables(), ",", "\"'", "\"'", - false); + public abstract boolean supportsQuotedIdentifiers(); - int numVariablesToSet = variablesToSet.size(); - - java.sql.Statement stmt = null; - - try { - stmt = getMetadataSafeStatement(); - - for (int i = 0; i < numVariablesToSet; i++) { - String variableValuePair = (String) variablesToSet.get(i); - - if (variableValuePair.startsWith("@")) { - stmt.executeUpdate("SET " + variableValuePair); - } else { - stmt.executeUpdate("SET SESSION " + variableValuePair); - } - } - } finally { - if (stmt != null) { - stmt.close(); - } - } - } - - } - /** - * Attempts to change the transaction isolation level for this - * Connection object to the one given. - * The constants defined in the interface Connection - * are the possible transaction isolation levels. - *

- * Note: If this method is called during a transaction, the result - * is implementation-defined. - * - * @param level one of the following Connection constants: - * Connection.TRANSACTION_READ_UNCOMMITTED, - * Connection.TRANSACTION_READ_COMMITTED, - * Connection.TRANSACTION_REPEATABLE_READ, or - * Connection.TRANSACTION_SERIALIZABLE. - * (Note that Connection.TRANSACTION_NONE cannot be used - * because it specifies that transactions are not supported.) - * @exception SQLException if a database access error occurs - * or the given parameter is not one of the Connection - * constants - * @see DatabaseMetaData#supportsTransactionIsolationLevel - * @see #getTransactionIsolation - */ - public synchronized void setTransactionIsolation(int level) throws SQLException { - checkClosed(); + * Does the server this connection is connected to + * support quoted identifiers? + */ + public abstract boolean supportsTransactions(); - if (this.hasIsolationLevels) { - String sql = null; - - boolean shouldSendSet = false; - - if (getAlwaysSendSetIsolation()) { - shouldSendSet = true; - } else { - if (level != this.isolationLevel) { - shouldSendSet = true; - } - } - - if (getUseLocalSessionState()) { - shouldSendSet = this.isolationLevel != level; - } - - if (shouldSendSet) { - switch (level) { - case java.sql.Connection.TRANSACTION_NONE: - throw SQLError.createSQLException("Transaction isolation level " - + "NONE not supported by MySQL"); - - case java.sql.Connection.TRANSACTION_READ_COMMITTED: - sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"; - - break; - - case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED: - sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"; - - break; - - case java.sql.Connection.TRANSACTION_REPEATABLE_READ: - sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"; - - break; - - case java.sql.Connection.TRANSACTION_SERIALIZABLE: - sql = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE"; - - break; - - default: - throw SQLError.createSQLException("Unsupported transaction " - + "isolation level '" + level + "'", - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); - } - - execSQL(null, sql, -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY,false, - this.database, true, false); - - this.isolationLevel = level; - } - } else { - throw SQLError.createSQLException("Transaction Isolation Levels are " - + "not supported on MySQL versions older than 3.23.36.", - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); - } - } - /** - * JDBC 2.0 Install a type-map object as the default type-map for this - * connection - * - * @param map - * the type mapping - * @throws SQLException - * if a database error occurs. + * Does the server this connection is connected to + * meet or exceed the given version? */ - public synchronized void setTypeMap(java.util.Map map) throws SQLException { - this.typeMap = map; - } + public abstract boolean versionMeetsMinimum(int major, int minor, + int subminor) throws SQLException; - /** - * Should we try to connect back to the master? We try when we've been - * failed over >= this.secondsBeforeRetryMaster _or_ we've issued > - * this.queriesIssuedFailedOver - * - * @return DOCUMENT ME! - */ - private boolean shouldFallBack() { - long secondsSinceFailedOver = (System.currentTimeMillis() - this.masterFailTimeMillis) / 1000; + public abstract void reportQueryTime(long millisOrNanos); + + public abstract boolean isAbonormallyLongQuery(long millisOrNanos); - // Done this way so we can set a condition in the debugger - boolean tryFallback = ((secondsSinceFailedOver >= getSecondsBeforeRetryMaster()) || (this.queriesIssuedFailedOver >= getQueriesBeforeRetryMaster())); - - return tryFallback; - } + public abstract void initializeExtension(Extension ex) throws SQLException; /** - * Used by MiniAdmin to shutdown a MySQL server - * - * @throws SQLException - * if the command can not be issued. + * Returns the -session- value of 'auto_increment_increment' from the server if it exists, + * or '1' if not. */ - public void shutdownServer() throws SQLException { - try { - this.io.sendCommand(MysqlDefs.SHUTDOWN, null, null, false, null); - } catch (Exception ex) { - throw SQLError.createSQLException("Unhandled exception '" + ex.toString() - + "'", SQLError.SQL_STATE_GENERAL_ERROR); - } - } - + public abstract int getAutoIncrementIncrement(); + /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * Does this connection have the same properties as another? */ - public boolean supportsIsolationLevel() { - return this.hasIsolationLevels; - } + public boolean hasSameProperties(Connection c); /** - * DOCUMENT ME! + * Returns the parsed and passed in properties for this connection. * - * @return DOCUMENT ME! + * @return */ - public boolean supportsQuotedIdentifiers() { - return this.hasQuotedIdentifiers; - } - - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean supportsTransactions() { - return this.transactionsSupported; - } - - /** - * Remove the given statement from the list of open statements - * - * @param stmt - * the Statement instance to remove - */ - void unregisterStatement(Statement stmt) { - if (this.openStatements != null) { - synchronized (this.openStatements) { - this.openStatements.remove(stmt); - } - } - } + public Properties getProperties(); - /** - * Called by statements on their .close() to let the connection know when it - * is safe to set the connection back to 'default' row limits. - * - * @param stmt - * the statement releasing it's max-rows requirement - * @throws SQLException - * if a database error occurs issuing the statement that sets - * the limit default. - */ - void unsetMaxRows(Statement stmt) throws SQLException { - synchronized (this.mutex) { - if (this.statementsUsingMaxRows != null) { - Object found = this.statementsUsingMaxRows.remove(stmt); + public String getHost(); - if ((found != null) - && (this.statementsUsingMaxRows.size() == 0)) { - execSQL(null, "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, - null, java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.database, true, false); + public void setProxy(MySQLConnection proxy); - this.maxRowsChanged = false; - } - } - } - } - - boolean useAnsiQuotedIdentifiers() { - return this.useAnsiQuotes; - } - /** - * Has maxRows() been set? + * Is the server this connection is connected to "local" (i.e. same host) as the application? * - * @return DOCUMENT ME! + * @return */ - boolean useMaxRows() { - synchronized (this.mutex) { - return this.maxRowsChanged; - } - } + public boolean isServerLocal() throws SQLException; - public boolean versionMeetsMinimum(int major, int minor, int subminor) - throws SQLException { - checkClosed(); + int getSessionMaxRows(); - return this.io.versionMeetsMinimum(major, minor, subminor); - } + void setSessionMaxRows(int max) throws SQLException; - protected String getErrorMessageEncoding() { - return errorMessageEncoding; - } + // JDBC-4.1 + // until we flip catalog/schema, this is a no-op + void setSchema(String schema) throws SQLException; - /* - * For testing failover scenarios - */ - private boolean hasTriedMasterFlag = false; + String getSchema() throws SQLException; - public void clearHasTriedMaster() { - this.hasTriedMasterFlag = false; - } + // JDBC-4.1 + void abort(Executor executor) throws SQLException; - public boolean hasTriedMaster() { - return this.hasTriedMasterFlag; - } + // JDBC-4.1 + void setNetworkTimeout(Executor executor, final int milliseconds) throws SQLException; - /** - * Returns cached metadata (or null if not cached) for the given query, - * which must match _exactly_. - * - * This method is synchronized by the caller on getMutex(), so if - * calling this method from internal code in the driver, make sure it's - * synchronized on the mutex that guards communication with the server. - * - * @param sql - * the query that is the key to the cache - * - * @return metadata cached for the given SQL, or none if it doesn't - * exist. - */ - protected CachedResultSetMetaData getCachedMetaData(String sql) { - if (this.resultSetMetadataCache != null) { - synchronized (this.resultSetMetadataCache) { - return (CachedResultSetMetaData) this.resultSetMetadataCache - .get(sql); - } - } + int getNetworkTimeout() throws SQLException; - return null; // no cache exists - } + // ************************** + // moved from MySQLConnection + // ************************** - /** - * Caches CachedResultSetMetaData that has been placed in the cache using - * the given SQL as a key. - * - * This method is synchronized by the caller on getMutex(), so if - * calling this method from internal code in the driver, make sure it's - * synchronized on the mutex that guards communication with the server. - * - * @param sql the query that the metadata pertains too. - * @param cachedMetaData metadata (if it exists) to populate the cache. - * @param resultSet the result set to retreive metadata from, or apply to. - * - * @throws SQLException - */ - protected void initializeResultsMetadataFromCache(String sql, - CachedResultSetMetaData cachedMetaData, ResultSet resultSet) - throws SQLException { + void abortInternal() throws SQLException; - if (cachedMetaData == null) { - - // read from results - cachedMetaData = new CachedResultSetMetaData(); - cachedMetaData.fields = resultSet.fields; + void checkClosed() throws SQLException; - // assume that users will use named-based - // lookups - resultSet.buildIndexMapping(); - resultSet.initializeWithMetadata(); - - if (resultSet instanceof UpdatableResultSet) { - ((UpdatableResultSet)resultSet).checkUpdatability(); - } - - cachedMetaData.columnNameToIndex = resultSet.columnNameToIndex; - cachedMetaData.fullColumnNameToIndex = resultSet.fullColumnNameToIndex; - - cachedMetaData.metadata = resultSet.getMetaData(); - - this.resultSetMetadataCache.put(sql, cachedMetaData); - } else { - // initialize results from cached data - resultSet.fields = cachedMetaData.fields; - resultSet.columnNameToIndex = cachedMetaData.columnNameToIndex; - resultSet.fullColumnNameToIndex = cachedMetaData.fullColumnNameToIndex; - resultSet.hasBuiltIndexMapping = true; - resultSet.initializeWithMetadata(); - - if (resultSet instanceof UpdatableResultSet) { - ((UpdatableResultSet)resultSet).checkUpdatability(); - } - } - } -} \ No newline at end of file + Object getConnectionMutex(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionFeatureNotAvailableException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionFeatureNotAvailableException.java (.../ConnectionFeatureNotAvailableException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionFeatureNotAvailableException.java (.../ConnectionFeatureNotAvailableException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -37,14 +36,16 @@ public class ConnectionFeatureNotAvailableException extends CommunicationsException { + static final long serialVersionUID = -5065030488729238287L; + /** * @param conn * @param lastPacketSentTimeMs * @param underlyingException */ - public ConnectionFeatureNotAvailableException(Connection conn, + public ConnectionFeatureNotAvailableException(MySQLConnection conn, long lastPacketSentTimeMs, Exception underlyingException) { - super(conn, lastPacketSentTimeMs, underlyingException); + super(conn, lastPacketSentTimeMs, 0, underlyingException); } /* Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionGroup.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionGroup.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionGroup.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,251 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class ConnectionGroup { + private String groupName; + private long connections = 0; + private long activeConnections = 0; + private HashMap connectionProxies = new HashMap(); + private Set hostList = new HashSet(); + private boolean isInitialized = false; + private long closedProxyTotalPhysicalConnections = 0; + private long closedProxyTotalTransactions = 0; + private int activeHosts = 0; + private Set closedHosts = new HashSet(); + + ConnectionGroup(String groupName){ + this.groupName = groupName; + } + + public long registerConnectionProxy(LoadBalancingConnectionProxy proxy, List localHostList){ + long currentConnectionId; + + synchronized (this){ + if(!this.isInitialized){ + this.hostList.addAll(localHostList); + this.isInitialized = true; + this.activeHosts = localHostList.size(); + } + currentConnectionId = ++connections; + this.connectionProxies.put(Long.valueOf(currentConnectionId), proxy); + } + this.activeConnections++; + + return currentConnectionId; + + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getGroupName() + */ + public String getGroupName(){ + return this.groupName; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getInitialHostList() + */ + public Collection getInitialHosts(){ + return this.hostList; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getActiveHostCount() + */ + public int getActiveHostCount(){ + return this.activeHosts; + } + + + public Collection getClosedHosts(){ + return this.closedHosts; + } + + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getTotalLogicalConnectionCount() + */ + public long getTotalLogicalConnectionCount(){ + return this.connections; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getActiveLogicalConnectionCount() + */ + public long getActiveLogicalConnectionCount(){ + return this.activeConnections; + } + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getActivePhysicalConnectionCount() + */ + public long getActivePhysicalConnectionCount(){ + long result = 0; + Map proxyMap = new HashMap(); + synchronized(this.connectionProxies){ + proxyMap.putAll(this.connectionProxies); + } + Iterator> i = proxyMap.entrySet().iterator(); + while(i.hasNext()){ + LoadBalancingConnectionProxy proxy = i.next().getValue(); + result += proxy.getActivePhysicalConnectionCount(); + + } + return result; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getTotalPhysicalConnectionCount() + */ + public long getTotalPhysicalConnectionCount(){ + long allConnections = this.closedProxyTotalPhysicalConnections; + Map proxyMap = new HashMap(); + synchronized(this.connectionProxies){ + proxyMap.putAll(this.connectionProxies); + } + Iterator> i = proxyMap.entrySet().iterator(); + while(i.hasNext()){ + LoadBalancingConnectionProxy proxy = i.next().getValue(); + allConnections += proxy.getTotalPhysicalConnectionCount(); + + } + return allConnections; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#getTotalTransactionCount() + */ + public long getTotalTransactionCount(){ + // need to account for closed connection proxies + long transactions = this.closedProxyTotalTransactions; + Map proxyMap = new HashMap(); + synchronized(this.connectionProxies){ + proxyMap.putAll(this.connectionProxies); + } + Iterator> i = proxyMap.entrySet().iterator(); + while(i.hasNext()){ + LoadBalancingConnectionProxy proxy = i.next().getValue(); + transactions += proxy.getTransactionCount(); + + } + return transactions; + } + + + public void closeConnectionProxy(LoadBalancingConnectionProxy proxy){ + this.activeConnections--; + this.connectionProxies.remove(Long.valueOf(proxy.getConnectionGroupProxyID())); + this.closedProxyTotalPhysicalConnections += proxy.getTotalPhysicalConnectionCount(); + this.closedProxyTotalTransactions += proxy.getTransactionCount(); + + } + + public void removeHost(String host) throws SQLException { + removeHost(host, false); + } + + public void removeHost(String host, boolean killExistingConnections) throws SQLException { + this.removeHost(host, killExistingConnections, true); + + } + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#removeHost(java.lang.String, boolean, boolean) + */ + public synchronized void removeHost(String host, boolean killExistingConnections, boolean waitForGracefulFailover) throws SQLException { + if(this.activeHosts == 1){ + throw SQLError.createSQLException("Cannot remove host, only one configured host active.", null); + } + + if(this.hostList.remove(host)){ + this.activeHosts--; + } else { + throw SQLError.createSQLException("Host is not configured: " + host, null); + } + + if(killExistingConnections){ + // make a local copy to keep synchronization overhead to minimum + Map proxyMap = new HashMap(); + synchronized(this.connectionProxies){ + proxyMap.putAll(this.connectionProxies); + } + + Iterator> i = proxyMap.entrySet().iterator(); + while(i.hasNext()){ + LoadBalancingConnectionProxy proxy = i.next().getValue(); + if(waitForGracefulFailover){ + proxy.removeHostWhenNotInUse(host); + } else { + proxy.removeHost(host); + } + } + } + this.closedHosts.add(host); + } + + + public void addHost(String host){ + addHost(host, false); + } + + + /* (non-Javadoc) + * @see com.mysql.jdbc.ConnectionGroupMBean#addHost(java.lang.String, boolean) + */ + public void addHost(String host, boolean forExisting){ + + synchronized(this){ + if(this.hostList.add(host)){ + this.activeHosts++; + } + } + // all new connections will have this host + if(!forExisting){ + return; + } + + + // make a local copy to keep synchronization overhead to minimum + Map proxyMap = new HashMap(); + synchronized(this.connectionProxies){ + proxyMap.putAll(this.connectionProxies); + } + + Iterator> i = proxyMap.entrySet().iterator(); + while(i.hasNext()){ + LoadBalancingConnectionProxy proxy = i.next().getValue(); + proxy.addHost(host); + } + + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionGroupManager.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionGroupManager.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionGroupManager.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,215 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.mysql.jdbc.jmx.LoadBalanceConnectionGroupManager; + +public class ConnectionGroupManager { + + private static HashMap GROUP_MAP = new HashMap(); + + private static LoadBalanceConnectionGroupManager mbean = new LoadBalanceConnectionGroupManager(); + + private static boolean hasRegisteredJmx = false; + + + public static synchronized ConnectionGroup getConnectionGroupInstance(String groupName){ + if(GROUP_MAP.containsKey(groupName)){ + return GROUP_MAP.get(groupName); + } + ConnectionGroup group = new ConnectionGroup(groupName); + GROUP_MAP.put(groupName, group); + return group; + } + + public static void registerJmx() throws SQLException { + if(hasRegisteredJmx){ + return; + } + + mbean.registerJmx(); + hasRegisteredJmx = true; + } + + public static ConnectionGroup getConnectionGroup(String groupName){ + return GROUP_MAP.get(groupName); + } + + private static Collection getGroupsMatching(String group){ + if(group == null || group.equals("")){ + Set s = new HashSet(); + + s.addAll(GROUP_MAP.values()); + return s; + } + Set s = new HashSet(); + ConnectionGroup o = GROUP_MAP.get(group); + if(o != null){ + s.add(o); + } + return s; + + } + + public static void addHost(String group, String host, boolean forExisting) { + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + cg.addHost(host, forExisting); + } + } + + public static int getActiveHostCount(String group) { + + Set active = new HashSet(); + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + active.addAll(cg.getInitialHosts()); + } + return active.size(); + } + + + + public static long getActiveLogicalConnectionCount(String group) { + int count = 0; + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + count += cg.getActiveLogicalConnectionCount(); + } + return count; + } + + public static long getActivePhysicalConnectionCount(String group) { + int count = 0; + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + count += cg.getActivePhysicalConnectionCount(); + } + return count; + } + + + public static int getTotalHostCount(String group) { + Collection s = getGroupsMatching(group); + Set hosts = new HashSet(); + for (ConnectionGroup cg : s) { + hosts.addAll(cg.getInitialHosts()); + hosts.addAll(cg.getClosedHosts()); + } + return hosts.size(); + } + + public static long getTotalLogicalConnectionCount(String group) { + long count = 0; + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + count += cg.getTotalLogicalConnectionCount(); + } + return count; + } + + public static long getTotalPhysicalConnectionCount(String group) { + long count = 0; + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + count += cg.getTotalPhysicalConnectionCount(); + } + return count; + } + + public static long getTotalTransactionCount(String group) { + long count = 0; + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + count += cg.getTotalTransactionCount(); + } + return count; + } + + public static void removeHost(String group, String host) throws SQLException { + removeHost(group, host, false); + } + + public static void removeHost(String group, String host, boolean removeExisting) throws SQLException { + Collection s = getGroupsMatching(group); + for (ConnectionGroup cg : s) { + cg.removeHost(host, removeExisting); + } + } + + public static String getActiveHostLists(String group) { + Collection s = getGroupsMatching(group); + Map hosts = new HashMap(); + for (ConnectionGroup cg : s) { + + Collection l = cg.getInitialHosts(); + for (String host : l) { + Integer o = hosts.get(host); + if(o == null){ + o = Integer.valueOf(1); + } else { + o = Integer.valueOf(o.intValue() + 1); + } + hosts.put(host, o); + + } + } + + StringBuffer sb = new StringBuffer(); + String sep = ""; + for(String host : hosts.keySet()) { + sb.append(sep); + sb.append(host); + sb.append('('); + sb.append(hosts.get(host)); + sb.append(')'); + sep = ","; + } + return sb.toString(); + } + + public static String getRegisteredConnectionGroups() { + Collection s = getGroupsMatching(null); + StringBuffer sb = new StringBuffer(); + String sep = ""; + for (ConnectionGroup cg : s) { + String group = cg.getGroupName(); + sb.append(sep); + sb.append(group); + sep = ","; + } + return sb.toString(); + + } + + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionImpl.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionImpl.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionImpl.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,6134 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.sql.Blob; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLPermission; +import java.sql.SQLWarning; +import java.sql.Savepoint; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Enumeration; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Random; +import java.util.Stack; +import java.util.TimeZone; +import java.util.Timer; +import java.util.TreeMap; +import java.util.concurrent.Executor; + +import com.mysql.jdbc.PreparedStatement.ParseInfo; +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.log.LogFactory; +import com.mysql.jdbc.log.LogUtils; +import com.mysql.jdbc.log.NullLogger; +import com.mysql.jdbc.profiler.ProfilerEvent; +import com.mysql.jdbc.profiler.ProfilerEventHandler; +import com.mysql.jdbc.util.LRUCache; + +/** + * A Connection represents a session with a specific database. Within the + * context of a Connection, SQL statements are executed and results are + * returned. + *

+ * A Connection's database is able to provide information describing its tables, + * its supported SQL grammar, its stored procedures, the capabilities of this + * connection, etc. This information is obtained with the getMetaData method. + *

+ * + * @author Mark Matthews + * @version $Id$ + * @see java.sql.Connection + */ +public class ConnectionImpl extends ConnectionPropertiesImpl implements + MySQLConnection { + + private static final long serialVersionUID = 2877471301981509474L; + + private static final SQLPermission SET_NETWORK_TIMEOUT_PERM = new SQLPermission("setNetworkTimeout"); + + private static final SQLPermission ABORT_PERM = new SQLPermission("abort"); + + private static final String JDBC_LOCAL_CHARACTER_SET_RESULTS = "jdbc.local.character_set_results"; + + public String getHost() { + return host; + } + + private MySQLConnection proxy = null; + + private InvocationHandler realProxy = null; + + public boolean isProxySet(){ + return this.proxy != null; + } + + public void setProxy(MySQLConnection proxy) { + this.proxy = proxy; + } + + public void setRealProxy(InvocationHandler proxy) { + this.realProxy = proxy; + } + + // We have to proxy ourselves when we're load balanced so that + // statements get routed to the right physical connection + // (when load balanced, we're a "logical" connection) + private MySQLConnection getProxy() { + return (proxy != null) ? proxy : (MySQLConnection) this; + } + + public MySQLConnection getLoadBalanceSafeProxy() { + return this.getProxy(); + } + + public Object getConnectionMutex() { + return (this.realProxy != null) ? this.realProxy : this; + } + + class ExceptionInterceptorChain implements ExceptionInterceptor { + List interceptors; + + ExceptionInterceptorChain(String interceptorClasses) throws SQLException { + interceptors = Util.loadExtensions(ConnectionImpl.this, props, interceptorClasses, "Connection.BadExceptionInterceptor", this); + } + + void addRingZero(ExceptionInterceptor interceptor) throws SQLException { + interceptors.add(0, interceptor); + } + + public SQLException interceptException(SQLException sqlEx, Connection conn) { + if (interceptors != null) { + Iterator iter = interceptors.iterator(); + + while (iter.hasNext()) { + sqlEx = ((ExceptionInterceptor)iter.next()).interceptException(sqlEx, ConnectionImpl.this); + } + } + + return sqlEx; + } + + public void destroy() { + if (interceptors != null) { + Iterator iter = interceptors.iterator(); + + while (iter.hasNext()) { + ((ExceptionInterceptor)iter.next()).destroy(); + } + } + + } + + public void init(Connection conn, Properties properties) throws SQLException { + if (interceptors != null) { + Iterator iter = interceptors.iterator(); + + while (iter.hasNext()) { + ((ExceptionInterceptor)iter.next()).init(conn, properties); + } + } + } + } + + /** + * Used as a key for caching callable statements which (may) depend on + * current catalog...In 5.0.x, they don't (currently), but stored procedure + * names soon will, so current catalog is a (hidden) component of the name. + */ + static class CompoundCacheKey { + String componentOne; + + String componentTwo; + + int hashCode; + + CompoundCacheKey(String partOne, String partTwo) { + this.componentOne = partOne; + this.componentTwo = partTwo; + + // Handle first component (in most cases, currentCatalog) + // being NULL.... + this.hashCode = (((this.componentOne != null) ? this.componentOne + : "") + this.componentTwo).hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj instanceof CompoundCacheKey) { + CompoundCacheKey another = (CompoundCacheKey) obj; + + boolean firstPartEqual = false; + + if (this.componentOne == null) { + firstPartEqual = (another.componentOne == null); + } else { + firstPartEqual = this.componentOne + .equals(another.componentOne); + } + + return (firstPartEqual && this.componentTwo + .equals(another.componentTwo)); + } + + return false; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.hashCode; + } + } + + /** + * Marker for character set converter not being available (not written, + * multibyte, etc) Used to prevent multiple instantiation requests. + */ + private static final Object CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object(); + + /** + * The mapping between MySQL charset names and Java charset names. + * Initialized by loadCharacterSetMapping() + */ + public static Map charsetMap; + + /** Default logger class name */ + protected static final String DEFAULT_LOGGER_CLASS = "com.mysql.jdbc.log.StandardLogger"; + + private final static int HISTOGRAM_BUCKETS = 20; + + /** Logger instance name */ + private static final String LOGGER_INSTANCE_NAME = "MySQL"; + + /** + * Map mysql transaction isolation level name to + * java.sql.Connection.TRANSACTION_XXX + */ + private static Map mapTransIsolationNameToValue = null; + + /** Null logger shared by all connections at startup */ + private static final Log NULL_LOGGER = new NullLogger(LOGGER_INSTANCE_NAME); + + protected static Map roundRobinStatsMap; + + private static final Map> serverCollationByUrl = new HashMap>(); + + /** + * Map for Java charsets of user defined charsets. We can't map them statically, because + * they can be different for different server URLs. + */ + private static final Map> serverJavaCharsetByUrl = new HashMap>(); + /** + * Map for user defined charsets. We can't map them statically, because + * they can be different for different server URLs. + */ + private static final Map> serverCustomCharsetByUrl = new HashMap>(); + /** + * Map for user defined charsets. We can't map them statically, because + * they can be different for different server URLs. + */ + private static final Map> serverCustomMblenByUrl = new HashMap>(); + + private CacheAdapter> serverConfigCache; + + private long queryTimeCount; + private double queryTimeSum; + private double queryTimeSumSquares; + private double queryTimeMean; + + private transient Timer cancelTimer; + + private List connectionLifecycleInterceptors; + + private static final Constructor JDBC_4_CONNECTION_CTOR; + + private static final int DEFAULT_RESULT_SET_TYPE = ResultSet.TYPE_FORWARD_ONLY; + + private static final int DEFAULT_RESULT_SET_CONCURRENCY = ResultSet.CONCUR_READ_ONLY; + + static { + mapTransIsolationNameToValue = new HashMap(8); + mapTransIsolationNameToValue.put("READ-UNCOMMITED", TRANSACTION_READ_UNCOMMITTED); + mapTransIsolationNameToValue.put("READ-UNCOMMITTED", TRANSACTION_READ_UNCOMMITTED); + mapTransIsolationNameToValue.put("READ-COMMITTED", TRANSACTION_READ_COMMITTED); + mapTransIsolationNameToValue.put("REPEATABLE-READ", TRANSACTION_REPEATABLE_READ); + mapTransIsolationNameToValue.put("SERIALIZABLE", TRANSACTION_SERIALIZABLE); + + if (Util.isJdbc4()) { + try { + JDBC_4_CONNECTION_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4Connection").getConstructor( + new Class[] { String.class, Integer.TYPE, + Properties.class, String.class, String.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_CONNECTION_CTOR = null; + } + } + + protected static SQLException appendMessageToException(SQLException sqlEx, + String messageToAppend, ExceptionInterceptor interceptor) { + String origMessage = sqlEx.getMessage(); + String sqlState = sqlEx.getSQLState(); + int vendorErrorCode = sqlEx.getErrorCode(); + + StringBuffer messageBuf = new StringBuffer(origMessage.length() + + messageToAppend.length()); + messageBuf.append(origMessage); + messageBuf.append(messageToAppend); + + SQLException sqlExceptionWithNewMessage = SQLError.createSQLException(messageBuf + .toString(), sqlState, vendorErrorCode, interceptor); + + // + // Try and maintain the original stack trace, + // only works on JDK-1.4 and newer + // + + try { + // Have to do this with reflection, otherwise older JVMs croak + Method getStackTraceMethod = null; + Method setStackTraceMethod = null; + Object theStackTraceAsObject = null; + + Class stackTraceElementClass = Class.forName("java.lang.StackTraceElement"); + Class stackTraceElementArrayClass = Array.newInstance( + stackTraceElementClass, new int[] { 0 }).getClass(); + + getStackTraceMethod = Throwable.class.getMethod("getStackTrace", + new Class[] {}); + + setStackTraceMethod = Throwable.class.getMethod("setStackTrace", + new Class[] { stackTraceElementArrayClass }); + + if (getStackTraceMethod != null && setStackTraceMethod != null) { + theStackTraceAsObject = getStackTraceMethod.invoke(sqlEx, + new Object[0]); + setStackTraceMethod.invoke(sqlExceptionWithNewMessage, + new Object[] { theStackTraceAsObject }); + } + } catch (NoClassDefFoundError noClassDefFound) { + + } catch (NoSuchMethodException noSuchMethodEx) { + + } catch (Throwable catchAll) { + + } + + return sqlExceptionWithNewMessage; + } + + public Timer getCancelTimer() { + synchronized (getConnectionMutex()) { + if (cancelTimer == null) { + boolean createdNamedTimer = false; + + // Use reflection magic to try this on JDK's 1.5 and newer, fallback to non-named + // timer on older VMs. + try { + Constructor ctr = Timer.class.getConstructor(new Class[] {String.class, Boolean.TYPE}); + + cancelTimer = ctr.newInstance(new Object[] { "MySQL Statement Cancellation Timer", Boolean.TRUE}); + createdNamedTimer = true; + } catch (Throwable t) { + createdNamedTimer = false; + } + + if (!createdNamedTimer) { + cancelTimer = new Timer(true); + } + } + + return cancelTimer; + } + } + + + /** + * Creates a connection instance -- We need to provide factory-style methods + * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise + * the class verifier complains when it tries to load JDBC4-only interface + * classes that are present in JDBC4 method signatures. + */ + + protected static Connection getInstance(String hostToConnectTo, + int portToConnectTo, Properties info, String databaseToConnectTo, + String url) throws SQLException { + if (!Util.isJdbc4()) { + return new ConnectionImpl(hostToConnectTo, portToConnectTo, info, + databaseToConnectTo, url); + } + + return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR, + new Object[] { + hostToConnectTo, Integer.valueOf(portToConnectTo), info, + databaseToConnectTo, url }, null); + } + + private static final Random random = new Random(); + + /** + * + * @param url + * @param hostList + * @return + */ + protected static synchronized int getNextRoundRobinHostIndex(String url, + List hostList) { + // we really do "random" here, because you don't get even + // distribution when this is coupled with connection pools + + int indexRange = hostList.size(); + + int index = random.nextInt(indexRange); + + return index; + } + + private static boolean nullSafeCompare(String s1, String s2) { + if (s1 == null && s2 == null) { + return true; + } + + if (s1 == null && s2 != null) { + return false; + } + + return s1 != null && s1.equals(s2); + } + + /** Are we in autoCommit mode? */ + private boolean autoCommit = true; + + /** A cache of SQL to parsed prepared statement parameters. */ + private CacheAdapter cachedPreparedStatementParams; + + /** + * For servers > 4.1.0, what character set is the metadata returned in? + */ + private String characterSetMetadata = null; + + /** + * The character set we want results and result metadata returned in (null == + * results in any charset, metadata in UTF-8). + */ + private String characterSetResultsOnServer = null; + + /** + * Holds cached mappings to charset converters to avoid static + * synchronization and at the same time save memory (each charset converter + * takes approx 65K of static data). + */ + private Map charsetConverterMap = new HashMap(CharsetMapping + .getNumberOfCharsetsConfigured()); + + /** The point in time when this connection was created */ + private long connectionCreationTimeMillis = 0; + + /** ID used when profiling */ + private long connectionId; + + /** The database we're currently using (called Catalog in JDBC terms). */ + private String database = null; + + /** Internal DBMD to use for various database-version specific features */ + private DatabaseMetaData dbmd = null; + + private TimeZone defaultTimeZone; + + /** The event sink to use for profiling */ + private ProfilerEventHandler eventSink; + + /** Why was this connection implicitly closed, if known? (for diagnostics) */ + private Throwable forceClosedReason; + + /** Does the server suuport isolation levels? */ + private boolean hasIsolationLevels = false; + + /** Does this version of MySQL support quoted identifiers? */ + private boolean hasQuotedIdentifiers = false; + + /** The hostname we're connected to */ + private String host = null; + + /** + * We need this 'bootstrapped', because 4.1 and newer will send fields back + * with this even before we fill this dynamically from the server. + */ + public Map indexToJavaCharset = new HashMap(); + + public Map indexToCustomMysqlCharset = null; //new HashMap(); + + private Map mysqlCharsetToCustomMblen = null; //new HashMap(); + + /** The I/O abstraction interface (network conn to MySQL server */ + private transient MysqlIO io = null; + + private boolean isClientTzUTC = false; + + /** Has this connection been closed? */ + private boolean isClosed = true; + + /** Is this connection associated with a global tx? */ + private boolean isInGlobalTx = false; + + /** Is this connection running inside a JDK-1.3 VM? */ + private boolean isRunningOnJDK13 = false; + + /** isolation level */ + private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED; + + private boolean isServerTzUTC = false; + + /** When did the last query finish? */ + private long lastQueryFinishedTime = 0; + + /** The logger we're going to use */ + private transient Log log = NULL_LOGGER; + + /** + * If gathering metrics, what was the execution time of the longest query so + * far ? + */ + private long longestQueryTimeMs = 0; + + /** Is the server configured to use lower-case table names only? */ + private boolean lowerCaseTableNames = false; + + /** When did the master fail? */ +// private long masterFailTimeMillis = 0L; + + private long maximumNumberTablesAccessed = 0; + + /** The max-rows setting for current session */ + private int sessionMaxRows = -1; + + /** When was the last time we reported metrics? */ + private long metricsLastReportedMs; + + private long minimumNumberTablesAccessed = Long.MAX_VALUE; + + /** The JDBC URL we're using */ + private String myURL = null; + + /** Does this connection need to be tested? */ + private boolean needsPing = false; + + private int netBufferLength = 16384; + + private boolean noBackslashEscapes = false; + + private long numberOfPreparedExecutes = 0; + + private long numberOfPrepares = 0; + + private long numberOfQueriesIssued = 0; + + private long numberOfResultSetsCreated = 0; + + private long[] numTablesMetricsHistBreakpoints; + + private int[] numTablesMetricsHistCounts; + + private long[] oldHistBreakpoints = null; + + private int[] oldHistCounts = null; + + /** A map of currently open statements */ + private Map openStatements; + + private LRUCache parsedCallableStatementCache; + + private boolean parserKnowsUnicode = false; + + /** The password we used */ + private String password = null; + + private long[] perfMetricsHistBreakpoints; + + private int[] perfMetricsHistCounts; + + /** Point of origin where this Connection was created */ + private String pointOfOrigin; + + /** The port number we're connected to (defaults to 3306) */ + private int port = 3306; + + /** Properties for this connection specified by user */ + protected Properties props = null; + + /** Should we retrieve 'info' messages from the server? */ + private boolean readInfoMsg = false; + + /** Are we in read-only mode? */ + private boolean readOnly = false; + + /** Cache of ResultSet metadata */ + protected LRUCache resultSetMetadataCache; + + /** The timezone of the server */ + private TimeZone serverTimezoneTZ = null; + + /** The map of server variables that we retrieve at connection init. */ + private Map serverVariables = null; + + private long shortestQueryTimeMs = Long.MAX_VALUE; + + private double totalQueryTimeMs = 0; + + /** Are transactions supported by the MySQL server we are connected to? */ + private boolean transactionsSupported = false; + + /** + * The type map for UDTs (not implemented, but used by some third-party + * vendors, most notably IBM WebSphere) + */ + private Map> typeMap; + + /** Has ANSI_QUOTES been enabled on the server? */ + private boolean useAnsiQuotes = false; + + /** The user we're connected as */ + private String user = null; + + /** + * Should we use server-side prepared statements? (auto-detected, but can be + * disabled by user) + */ + private boolean useServerPreparedStmts = false; + + private LRUCache serverSideStatementCheckCache; + private LRUCache serverSideStatementCache; + private Calendar sessionCalendar; + + private Calendar utcCalendar; + + private String origHostToConnectTo; + + // we don't want to be able to publicly clone this... + + private int origPortToConnectTo; + + private String origDatabaseToConnectTo; + + private String errorMessageEncoding = "Cp1252"; // to begin with, changes after we talk to the server + + private boolean usePlatformCharsetConverters; + + /* + * For testing failover scenarios + */ + private boolean hasTriedMasterFlag = false; + + /** + * The comment (if any) that we'll prepend to all statements + * sent to the server (to show up in "SHOW PROCESSLIST") + */ + private String statementComment = null; + + private boolean storesLowerCaseTableName; + + private List statementInterceptors; + + /** + * If a CharsetEncoder is required for escaping. Needed for SJIS and related + * problems with \u00A5. + */ + private boolean requiresEscapingEncoder; + + private String hostPortPair; + + /**' + * For the delegate only + */ + protected ConnectionImpl() { + } + + /** + * Creates a connection to a MySQL Server. + * + * @param hostToConnectTo + * the hostname of the database server + * @param portToConnectTo + * the port number the server is listening on + * @param info + * a Properties[] list holding the user and password + * @param databaseToConnectTo + * the database to connect to + * @param url + * the URL of the connection + * @param d + * the Driver instantation of the connection + * @exception SQLException + * if a database access error occurs + */ + public ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info, + String databaseToConnectTo, String url) + throws SQLException { + + this.connectionCreationTimeMillis = System.currentTimeMillis(); + + if (databaseToConnectTo == null) { + databaseToConnectTo = ""; + } + + // Stash away for later, used to clone this connection for Statement.cancel + // and Statement.setQueryTimeout(). + // + + this.origHostToConnectTo = hostToConnectTo; + this.origPortToConnectTo = portToConnectTo; + this.origDatabaseToConnectTo = databaseToConnectTo; + + try { + Blob.class.getMethod("truncate", new Class[] {Long.TYPE}); + + this.isRunningOnJDK13 = false; + } catch (NoSuchMethodException nsme) { + this.isRunningOnJDK13 = true; + } + + this.sessionCalendar = new GregorianCalendar(); + this.utcCalendar = new GregorianCalendar(); + this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT")); + + // + // Normally, this code would be in initializeDriverProperties, + // but we need to do this as early as possible, so we can start + // logging to the 'correct' place as early as possible...this.log + // points to 'NullLogger' for every connection at startup to avoid + // NPEs and the overhead of checking for NULL at every logging call. + // + // We will reset this to the configured logger during properties + // initialization. + // + this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME, getExceptionInterceptor()); + + // We store this per-connection, due to static synchronization + // issues in Java's built-in TimeZone class... + this.defaultTimeZone = Util.getDefaultTimeZone(); + + if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) { + this.isClientTzUTC = true; + } else { + this.isClientTzUTC = false; + } + + this.openStatements = new HashMap(); + + if (NonRegisteringDriver.isHostPropertiesList(hostToConnectTo)) { + Properties hostSpecificProps = NonRegisteringDriver.expandHostKeyValues(hostToConnectTo); + + Enumeration propertyNames = hostSpecificProps.propertyNames(); + + while (propertyNames.hasMoreElements()) { + String propertyName = propertyNames.nextElement().toString(); + String propertyValue = hostSpecificProps.getProperty(propertyName); + + info.setProperty(propertyName, propertyValue); + } + } else { + + if (hostToConnectTo == null) { + this.host = "localhost"; + this.hostPortPair = this.host + ":" + portToConnectTo; + } else { + this.host = hostToConnectTo; + + if (hostToConnectTo.indexOf(":") == -1) { + this.hostPortPair = this.host + ":" + portToConnectTo; + } else { + this.hostPortPair = this.host; + } + } + } + + this.port = portToConnectTo; + + this.database = databaseToConnectTo; + this.myURL = url; + this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY); + this.password = info + .getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY); + + if ((this.user == null) || this.user.equals("")) { + this.user = ""; + } + + if (this.password == null) { + this.password = ""; + } + + this.props = info; + + + + initializeDriverProperties(info); + + if (getUseUsageAdvisor()) { + this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable()); + } else { + this.pointOfOrigin = ""; + } + + try { + this.dbmd = getMetaData(false, false); + initializeSafeStatementInterceptors(); + createNewIO(false); + unSafeStatementInterceptors(); + } catch (SQLException ex) { + cleanup(ex); + + // don't clobber SQL exceptions + throw ex; + } catch (Exception ex) { + cleanup(ex); + + StringBuffer mesg = new StringBuffer(128); + + if (!getParanoid()) { + mesg.append("Cannot connect to MySQL server on "); + mesg.append(this.host); + mesg.append(":"); + mesg.append(this.port); + mesg.append(".\n\n"); + mesg.append("Make sure that there is a MySQL server "); + mesg.append("running on the machine/port you are trying "); + mesg + .append("to connect to and that the machine this software is " + + "running on "); + mesg.append("is able to connect to this host/port " + + "(i.e. not firewalled). "); + mesg + .append("Also make sure that the server has not been started " + + "with the --skip-networking "); + mesg.append("flag.\n\n"); + } else { + mesg.append("Unable to connect to database."); + } + + SQLException sqlEx = SQLError.createSQLException(mesg.toString(), + SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, getExceptionInterceptor()); + + sqlEx.initCause(ex); + + throw sqlEx; + } + + NonRegisteringDriver.trackConnection(this); + } + + public void unSafeStatementInterceptors() throws SQLException { + + ArrayList unSafedStatementInterceptors = new ArrayList(this.statementInterceptors.size()); + + for (int i = 0; i < this.statementInterceptors.size(); i++) { + NoSubInterceptorWrapper wrappedInterceptor = (NoSubInterceptorWrapper) this.statementInterceptors.get(i); + + unSafedStatementInterceptors.add(wrappedInterceptor.getUnderlyingInterceptor()); + } + + this.statementInterceptors = unSafedStatementInterceptors; + + if (this.io != null) { + this.io.setStatementInterceptors(this.statementInterceptors); + } + } + + public void initializeSafeStatementInterceptors() throws SQLException { + this.isClosed = false; + + List unwrappedInterceptors = Util.loadExtensions(this, this.props, + getStatementInterceptors(), + "MysqlIo.BadStatementInterceptor", getExceptionInterceptor()); + + this.statementInterceptors = new ArrayList(unwrappedInterceptors.size()); + + for (int i = 0; i < unwrappedInterceptors.size(); i++) { + Extension interceptor = unwrappedInterceptors.get(i); + + // adapt older versions of statement interceptors, handle the case where something wants v2 + // functionality but wants to run with an older driver + if (interceptor instanceof StatementInterceptor) { + if (ReflectiveStatementInterceptorAdapter.getV2PostProcessMethod(interceptor.getClass()) != null) { + this.statementInterceptors.add(new NoSubInterceptorWrapper(new ReflectiveStatementInterceptorAdapter((StatementInterceptor) interceptor))); + } else { + this.statementInterceptors.add(new NoSubInterceptorWrapper(new V1toV2StatementInterceptorAdapter((StatementInterceptor) interceptor))); + } + } else { + this.statementInterceptors.add(new NoSubInterceptorWrapper((StatementInterceptorV2)interceptor)); + } + } + + + } + + public List getStatementInterceptorsInstances() { + return this.statementInterceptors; + } + + private void addToHistogram(int[] histogramCounts, + long[] histogramBreakpoints, long value, int numberOfTimes, + long currentLowerBound, long currentUpperBound) { + if (histogramCounts == null) { + createInitialHistogram(histogramBreakpoints, + currentLowerBound, currentUpperBound); + } else { + for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { + if (histogramBreakpoints[i] >= value) { + histogramCounts[i] += numberOfTimes; + + break; + } + } + } + } + + private void addToPerformanceHistogram(long value, int numberOfTimes) { + checkAndCreatePerformanceHistogram(); + + addToHistogram(this.perfMetricsHistCounts, + this.perfMetricsHistBreakpoints, value, numberOfTimes, + this.shortestQueryTimeMs == Long.MAX_VALUE ? 0 + : this.shortestQueryTimeMs, this.longestQueryTimeMs); + } + + private void addToTablesAccessedHistogram(long value, int numberOfTimes) { + checkAndCreateTablesAccessedHistogram(); + + addToHistogram(this.numTablesMetricsHistCounts, + this.numTablesMetricsHistBreakpoints, value, numberOfTimes, + this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0 + : this.minimumNumberTablesAccessed, + this.maximumNumberTablesAccessed); + } + + /** + * Builds the map needed for 4.1.0 and newer servers that maps field-level + * charset/collation info to a java character encoding name. + * + * @throws SQLException + * DOCUMENT ME! + */ + private void buildCollationMapping() throws SQLException { + + Map javaCharset = null; + Map sortedCollationMap = null; + Map customCharset = null; + Map customMblen = null; + + if (getCacheServerConfiguration()) { + synchronized (serverJavaCharsetByUrl) { + javaCharset = serverJavaCharsetByUrl.get(getURL()); + sortedCollationMap = serverCollationByUrl.get(getURL()); + customCharset = serverCustomCharsetByUrl.get(getURL()); + customMblen = serverCustomMblenByUrl.get(getURL()); + } + } + + if (javaCharset == null) { + javaCharset = new HashMap(); + + if (versionMeetsMinimum(4, 1, 0) && getDetectCustomCollations()) { + + java.sql.Statement stmt = null; + java.sql.ResultSet results = null; + + try { + sortedCollationMap = new TreeMap(); + customCharset = new HashMap(); + customMblen = new HashMap(); + + stmt = getMetadataSafeStatement(); + + try { + results = stmt.executeQuery("SHOW COLLATION"); + if (versionMeetsMinimum(5, 0, 0)) { + Util.resultSetToMap(sortedCollationMap, results, 3, 2); + } else { + while (results.next()) { + sortedCollationMap.put(results.getLong(3), results.getString(2)); + } + } + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + + for (Iterator> indexIter = sortedCollationMap.entrySet().iterator(); indexIter.hasNext();) { + Map.Entry indexEntry = indexIter.next(); + + int collationIndex = indexEntry.getKey().intValue(); + String charsetName = indexEntry.getValue(); + + javaCharset.put(collationIndex, getJavaEncodingForMysqlEncoding(charsetName)); + + // if no static map for charsetIndex + // or server has a different mapping then our static map, + // adding it to custom map + if (collationIndex >= CharsetMapping.MAP_SIZE || + !charsetName.equals(CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(collationIndex))) { + customCharset.put(collationIndex, charsetName); + } + + // if no static map for charsetName adding to custom map + if (!CharsetMapping.STATIC_CHARSET_TO_NUM_BYTES_MAP.containsKey(charsetName) && + !CharsetMapping.STATIC_4_0_CHARSET_TO_NUM_BYTES_MAP.containsKey(charsetName)) { + customMblen.put(charsetName, null); + } + } + + // if there is a number of custom charsets we should execute SHOW CHARACTER SET to know theirs mblen + if (customMblen.size() > 0) { + try { + results = stmt.executeQuery("SHOW CHARACTER SET"); + while (results.next()) { + String charsetName = results.getString("Charset"); + if (customMblen.containsKey(charsetName)) { + customMblen.put(charsetName, results.getInt("Maxlen")); + } + } + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + } + + if (getCacheServerConfiguration()) { + synchronized (serverJavaCharsetByUrl) { + serverJavaCharsetByUrl.put(getURL(), javaCharset); + serverCollationByUrl.put(getURL(), sortedCollationMap); + serverCustomCharsetByUrl.put(getURL(), customCharset); + serverCustomMblenByUrl.put(getURL(), customMblen); + } + } + + + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } finally { + if (results != null) { + try { + results.close(); + } catch (java.sql.SQLException sqlE) { + // ignore + } + } + + if (stmt != null) { + try { + stmt.close(); + } catch (java.sql.SQLException sqlE) { + // ignore + } + } + } + } else { + for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) { + javaCharset.put(i, getJavaEncodingForMysqlEncoding(CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(i))); + } + if (getCacheServerConfiguration()) { + synchronized (serverJavaCharsetByUrl) { + serverJavaCharsetByUrl.put(getURL(), javaCharset); + } + } + } + + + } + + this.indexToJavaCharset = Collections.unmodifiableMap(javaCharset); + if (customCharset != null) { + this.indexToCustomMysqlCharset = Collections.unmodifiableMap(customCharset); + } + if (customMblen != null) { + this.mysqlCharsetToCustomMblen = Collections.unmodifiableMap(customMblen); + } + } + + public String getJavaEncodingForMysqlEncoding(String mysqlEncoding) throws SQLException { + + if (versionMeetsMinimum(4, 1, 0) && "latin1".equalsIgnoreCase(mysqlEncoding)) { + return "Cp1252"; + } + + return CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlEncoding); + } + + private boolean canHandleAsServerPreparedStatement(String sql) + throws SQLException { + if (sql == null || sql.length() == 0) { + return true; + } + + if (!this.useServerPreparedStmts) { + return false; + } + + if (getCachePreparedStatements()) { + synchronized (this.serverSideStatementCheckCache) { + Boolean flag = (Boolean)this.serverSideStatementCheckCache.get(sql); + + if (flag != null) { + return flag.booleanValue(); + } + + boolean canHandle = canHandleAsServerPreparedStatementNoCache(sql); + + if (sql.length() < getPreparedStatementCacheSqlLimit()) { + this.serverSideStatementCheckCache.put(sql, + canHandle ? Boolean.TRUE : Boolean.FALSE); + } + + return canHandle; + } + } + + return canHandleAsServerPreparedStatementNoCache(sql); + } + + private boolean canHandleAsServerPreparedStatementNoCache(String sql) + throws SQLException { + + // Can't use server-side prepare for CALL + if (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "CALL")) { + return false; + } + + boolean canHandleAsStatement = true; + + if (!versionMeetsMinimum(5, 0, 7) && + (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "SELECT") + || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, + "DELETE") + || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, + "INSERT") + || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, + "UPDATE") + || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, + "REPLACE"))) { + + // check for limit ?[,?] + + /* + * The grammar for this (from the server) is: ULONG_NUM | ULONG_NUM + * ',' ULONG_NUM | ULONG_NUM OFFSET_SYM ULONG_NUM + */ + + int currentPos = 0; + int statementLength = sql.length(); + int lastPosToLook = statementLength - 7; // "LIMIT ".length() + boolean allowBackslashEscapes = !this.noBackslashEscapes; + char quoteChar = this.useAnsiQuotes ? '"' : '\''; + boolean foundLimitWithPlaceholder = false; + + while (currentPos < lastPosToLook) { + int limitStart = StringUtils.indexOfIgnoreCaseRespectQuotes( + currentPos, sql, "LIMIT ", quoteChar, + allowBackslashEscapes); + + if (limitStart == -1) { + break; + } + + currentPos = limitStart + 7; + + while (currentPos < statementLength) { + char c = sql.charAt(currentPos); + + // + // Have we reached the end + // of what can be in a LIMIT clause? + // + + if (!Character.isDigit(c) && !Character.isWhitespace(c) + && c != ',' && c != '?') { + break; + } + + if (c == '?') { + foundLimitWithPlaceholder = true; + break; + } + + currentPos++; + } + } + + canHandleAsStatement = !foundLimitWithPlaceholder; + } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "XA ")) { + canHandleAsStatement = false; + } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "CREATE TABLE")) { + canHandleAsStatement = false; + } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "DO")) { + canHandleAsStatement = false; + } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "SET")) { + canHandleAsStatement = false; + } + + + + return canHandleAsStatement; + } + + /** + * Changes the user on this connection by performing a re-authentication. If + * authentication fails, the connection will remain under the context of the + * current user. + * + * @param userName + * the username to authenticate with + * @param newPassword + * the password to authenticate with + * @throws SQLException + * if authentication fails, or some other error occurs while + * performing the command. + */ + public void changeUser(String userName, String newPassword) + throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + if ((userName == null) || userName.equals("")) { + userName = ""; + } + + if (newPassword == null) { + newPassword = ""; + } + + // reset maxRows to default value + this.sessionMaxRows = -1; + + try { + this.io.changeUser(userName, newPassword, this.database); + } catch(SQLException ex) { + if (versionMeetsMinimum(5, 6, 13) && "28000".equals(ex.getSQLState())) { + cleanup(ex); + } + throw ex; + } + this.user = userName; + this.password = newPassword; + + if (versionMeetsMinimum(4, 1, 0)) { + configureClientCharacterSet(true); + } + + setSessionVariables(); + + setupServerForTruncationChecks(); + } + } + + private boolean characterSetNamesMatches(String mysqlEncodingName) { + // set names is equivalent to character_set_client ..._results and ..._connection, + // but we set _results later, so don't check it here. + return (mysqlEncodingName != null && + mysqlEncodingName.equalsIgnoreCase(this.serverVariables.get("character_set_client")) && + mysqlEncodingName.equalsIgnoreCase(this.serverVariables.get("character_set_connection"))); + } + + private void checkAndCreatePerformanceHistogram() { + if (this.perfMetricsHistCounts == null) { + this.perfMetricsHistCounts = new int[HISTOGRAM_BUCKETS]; + } + + if (this.perfMetricsHistBreakpoints == null) { + this.perfMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS]; + } + } + + private void checkAndCreateTablesAccessedHistogram() { + if (this.numTablesMetricsHistCounts == null) { + this.numTablesMetricsHistCounts = new int[HISTOGRAM_BUCKETS]; + } + + if (this.numTablesMetricsHistBreakpoints == null) { + this.numTablesMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS]; + } + } + + public void checkClosed() throws SQLException { + if (this.isClosed) { + throwConnectionClosedException(); + } + } + + public void throwConnectionClosedException() throws SQLException { + StringBuffer messageBuf = new StringBuffer( + "No operations allowed after connection closed."); + + SQLException ex = SQLError.createSQLException(messageBuf.toString(), + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor()); + + if (this.forceClosedReason != null) { + ex.initCause(this.forceClosedReason); + } + + throw ex; + } + + /** + * If useUnicode flag is set and explicit client character encoding isn't + * specified then assign encoding from server if any. + * + * @throws SQLException + * DOCUMENT ME! + */ + private void checkServerEncoding() throws SQLException { + if (getUseUnicode() && (getEncoding() != null)) { + // spec'd by client, don't map + return; + } + + String serverEncoding = this.serverVariables.get("character_set"); + + if (serverEncoding == null) { + // must be 4.1.1 or newer? + serverEncoding = this.serverVariables.get("character_set_server"); + } + + String mappedServerEncoding = null; + + if (serverEncoding != null) { + try { + mappedServerEncoding = getJavaEncodingForMysqlEncoding(serverEncoding + .toUpperCase(Locale.ENGLISH)); + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + } + + // + // First check if we can do the encoding ourselves + // + if (!getUseUnicode() && (mappedServerEncoding != null)) { + SingleByteCharsetConverter converter = getCharsetConverter(mappedServerEncoding); + + if (converter != null) { // we know how to convert this ourselves + setUseUnicode(true); // force the issue + setEncoding(mappedServerEncoding); + + return; + } + } + + // + // Now, try and find a Java I/O converter that can do + // the encoding for us + // + if (serverEncoding != null) { + if (mappedServerEncoding == null) { + // We don't have a mapping for it, so try + // and canonicalize the name.... + if (Character.isLowerCase(serverEncoding.charAt(0))) { + char[] ach = serverEncoding.toCharArray(); + ach[0] = Character.toUpperCase(serverEncoding.charAt(0)); + setEncoding(new String(ach)); + } + } + + if (mappedServerEncoding == null) { + throw SQLError.createSQLException("Unknown character encoding on server '" + + serverEncoding + + "', use 'characterEncoding=' property " + + " to provide correct mapping", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor()); + } + + // + // Attempt to use the encoding, and bail out if it + // can't be used + // + try { + StringUtils.getBytes("abc",mappedServerEncoding); + setEncoding(mappedServerEncoding); + setUseUnicode(true); + } catch (UnsupportedEncodingException UE) { + throw SQLError.createSQLException( + "The driver can not map the character encoding '" + + getEncoding() + + "' that your server is using " + + "to a character encoding your JVM understands. You " + + "can specify this mapping manually by adding \"useUnicode=true\" " + + "as well as \"characterEncoding=[an_encoding_your_jvm_understands]\" " + + "to your JDBC URL.", "0S100", getExceptionInterceptor()); + } + } + } + + /** + * Set transaction isolation level to the value received from server if any. + * Is called by connectionInit(...) + * + * @throws SQLException + * DOCUMENT ME! + */ + private void checkTransactionIsolationLevel() throws SQLException { + String txIsolationName = null; + + if (versionMeetsMinimum(4, 0, 3)) { + txIsolationName = "tx_isolation"; + } else { + txIsolationName = "transaction_isolation"; + } + + String s = this.serverVariables.get(txIsolationName); + + if (s != null) { + Integer intTI = mapTransIsolationNameToValue.get(s); + + if (intTI != null) { + this.isolationLevel = intTI.intValue(); + } + } + } + + /** + * Clobbers the physical network connection and marks + * this connection as closed. + * + * @throws SQLException + */ + public void abortInternal() throws SQLException { + if (this.io != null) { + try { + this.io.forceClose(); + } catch (Throwable t) { + // can't do anything about it, and we're forcibly aborting + } + this.io.releaseResources(); + this.io = null; + } + + this.isClosed = true; + } + + /** + * Destroys this connection and any underlying resources + * + * @param fromWhere + * DOCUMENT ME! + * @param whyCleanedUp + * DOCUMENT ME! + */ + private void cleanup(Throwable whyCleanedUp) { + try { + if (this.io != null) { + if (isClosed()) { + this.io.forceClose(); + } else { + realClose(false, false, false, whyCleanedUp); + } + } + } catch (SQLException sqlEx) { + // ignore, we're going away. + ; + } + + this.isClosed = true; + } + + public void clearHasTriedMaster() { + this.hasTriedMasterFlag = false; + } + + /** + * After this call, getWarnings returns null until a new warning is reported + * for this connection. + * + * @exception SQLException + * if a database access error occurs + */ + public void clearWarnings() throws SQLException { + // firstWarning = null; + } + + /** + * DOCUMENT ME! + * + * @param sql + * DOCUMENT ME! + * @return DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + public java.sql.PreparedStatement clientPrepareStatement(String sql) + throws SQLException { + return clientPrepareStatement(sql, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY); + } + + /** + * @see Connection#prepareStatement(String, int) + */ + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + java.sql.PreparedStatement pStmt = clientPrepareStatement(sql); + + ((com.mysql.jdbc.PreparedStatement) pStmt) + .setRetrieveGeneratedKeys(autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS); + + return pStmt; + } + + /** + * DOCUMENT ME! + * + * @param sql + * DOCUMENT ME! + * @param resultSetType + * DOCUMENT ME! + * @param resultSetConcurrency + * DOCUMENT ME! + * @return DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + return clientPrepareStatement(sql, resultSetType, resultSetConcurrency, true); + } + + + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + boolean processEscapeCodesIfNeeded) throws SQLException { + checkClosed(); + + String nativeSql = processEscapeCodesIfNeeded && getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; + + PreparedStatement pStmt = null; + + if (getCachePreparedStatements()) { + PreparedStatement.ParseInfo pStmtInfo = this.cachedPreparedStatementParams.get(nativeSql); + + if (pStmtInfo == null) { + pStmt = com.mysql.jdbc.PreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, + this.database); + + this.cachedPreparedStatementParams.put(nativeSql, pStmt + .getParseInfo()); + } else { + pStmt = new com.mysql.jdbc.PreparedStatement(getLoadBalanceSafeProxy(), nativeSql, + this.database, pStmtInfo); + } + } else { + pStmt = com.mysql.jdbc.PreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, + this.database); + } + + pStmt.setResultSetType(resultSetType); + pStmt.setResultSetConcurrency(resultSetConcurrency); + + return pStmt; + } + + /** + * @see java.sql.Connection#prepareStatement(String, int[]) + */ + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + + PreparedStatement pStmt = (PreparedStatement) clientPrepareStatement(sql); + + pStmt + .setRetrieveGeneratedKeys((autoGenKeyIndexes != null) + && (autoGenKeyIndexes.length > 0)); + + return pStmt; + } + + /** + * @see java.sql.Connection#prepareStatement(String, String[]) + */ + public java.sql.PreparedStatement clientPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + PreparedStatement pStmt = (PreparedStatement) clientPrepareStatement(sql); + + pStmt + .setRetrieveGeneratedKeys((autoGenKeyColNames != null) + && (autoGenKeyColNames.length > 0)); + + return pStmt; + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return clientPrepareStatement(sql, resultSetType, resultSetConcurrency, true); + } + + // --------------------------JDBC 2.0----------------------------- + + /** + * In some cases, it is desirable to immediately release a Connection's + * database and JDBC resources instead of waiting for them to be + * automatically released (cant think why off the top of my head) Note: + * A Connection is automatically closed when it is garbage collected. + * Certain fatal errors also result in a closed connection. + * + * @exception SQLException + * if a database access error occurs + */ + public void close() throws SQLException { + synchronized (getConnectionMutex()) { + if (this.connectionLifecycleInterceptors != null) { + new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + void forEach(Extension each) throws SQLException { + ((ConnectionLifecycleInterceptor)each).close(); + } + }.doForAll(); + } + + realClose(true, true, false, null); + } + } + + /** + * Closes all currently open statements. + * + * @throws SQLException + * DOCUMENT ME! + */ + private void closeAllOpenStatements() throws SQLException { + SQLException postponedException = null; + + if (this.openStatements != null) { + List currentlyOpenStatements = new ArrayList(); // we need this to + // avoid + // ConcurrentModificationEx + + for (Iterator iter = this.openStatements.keySet().iterator(); iter.hasNext();) { + currentlyOpenStatements.add(iter.next()); + } + + int numStmts = currentlyOpenStatements.size(); + + for (int i = 0; i < numStmts; i++) { + StatementImpl stmt = (StatementImpl) currentlyOpenStatements.get(i); + + try { + stmt.realClose(false, true); + } catch (SQLException sqlEx) { + postponedException = sqlEx; // throw it later, cleanup all + // statements first + } + } + + if (postponedException != null) { + throw postponedException; + } + } + } + + private void closeStatement(java.sql.Statement stmt) { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException sqlEx) { + ; // ignore + } + + stmt = null; + } + } + + /** + * The method commit() makes all changes made since the previous + * commit/rollback permanent and releases any database locks currently held + * by the Connection. This method should only be used when auto-commit has + * been disabled. + *

+ * Note: MySQL does not support transactions, so this method is a + * no-op. + *

+ * + * @exception SQLException + * if a database access error occurs + * @see setAutoCommit + */ + public void commit() throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + try { + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + if (!((ConnectionLifecycleInterceptor)each).commit()) { + this.stopIterating = true; + } + } + }; + + iter.doForAll(); + + if (!iter.fullIteration()) { + return; + } + } + + // no-op if _relaxAutoCommit == true + if (this.autoCommit && !getRelaxAutoCommit()) { + throw SQLError.createSQLException("Can't call commit when autocommit=true", getExceptionInterceptor()); + } else if (this.transactionsSupported) { + if (getUseLocalTransactionState() && versionMeetsMinimum(5, 0, 0)) { + if (!this.io.inTransactionOnServer()) { + return; // effectively a no-op + } + } + + execSQL(null, "commit", -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, + false); + } + } catch (SQLException sqlException) { + if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE + .equals(sqlException.getSQLState())) { + throw SQLError + .createSQLException( + "Communications link failure during commit(). Transaction resolution unknown.", + SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, + getExceptionInterceptor()); + } + + throw sqlException; + } finally { + this.needsPing = this.getReconnectAtTxEnd(); + } + } + return; + } + + /** + * Configures client-side properties for character set information. + * + * @throws SQLException + * if unable to configure the specified character set. + */ + private void configureCharsetProperties() throws SQLException { + if (getEncoding() != null) { + // Attempt to use the encoding, and bail out if it + // can't be used + try { + String testString = "abc"; + StringUtils.getBytes(testString, getEncoding()); + } catch (UnsupportedEncodingException UE) { + // Try the MySQL character encoding, then.... + String oldEncoding = getEncoding(); + + try { + setEncoding(getJavaEncodingForMysqlEncoding(oldEncoding)); + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + if (getEncoding() == null) { + throw SQLError.createSQLException( + "Java does not support the MySQL character encoding " + + " " + "encoding '" + oldEncoding + "'.", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor()); + } + + try { + String testString = "abc"; + StringUtils.getBytes(testString, getEncoding()); + } catch (UnsupportedEncodingException encodingEx) { + throw SQLError.createSQLException("Unsupported character " + + "encoding '" + getEncoding() + "'.", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor()); + } + } + } + } + + /** + * Sets up client character set for MySQL-4.1 and newer if the user This + * must be done before any further communication with the server! + * + * @return true if this routine actually configured the client character + * set, or false if the driver needs to use 'older' methods to + * detect the character set, as it is connected to a MySQL server + * older than 4.1.0 + * @throws SQLException + * if an exception happens while sending 'SET NAMES' to the + * server, or the server sends character set information that + * the client doesn't know about. + */ + private boolean configureClientCharacterSet(boolean dontCheckServerMatch) throws SQLException { + String realJavaEncoding = getEncoding(); + boolean characterSetAlreadyConfigured = false; + + try { + if (versionMeetsMinimum(4, 1, 0)) { + characterSetAlreadyConfigured = true; + + setUseUnicode(true); + + configureCharsetProperties(); + realJavaEncoding = getEncoding(); // we need to do this again + // to grab this for + // versions > 4.1.0 + + try { + + // Fault injection for testing server character set indices + + if (props != null && props.getProperty("com.mysql.jdbc.faultInjection.serverCharsetIndex") != null) { + this.io.serverCharsetIndex = Integer.parseInt( + props.getProperty( + "com.mysql.jdbc.faultInjection.serverCharsetIndex")); + } + + String serverEncodingToSet = + CharsetMapping.INDEX_TO_CHARSET[this.io.serverCharsetIndex]; + + if (serverEncodingToSet == null || serverEncodingToSet.length() == 0) { + if (realJavaEncoding != null) { + // user knows best, try it + setEncoding(realJavaEncoding); + } else { + throw SQLError.createSQLException( + "Unknown initial character set index '" + + this.io.serverCharsetIndex + + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + // "latin1" on MySQL-4.1.0+ is actually CP1252, not ISO8859_1 + if (versionMeetsMinimum(4, 1, 0) && + "ISO8859_1".equalsIgnoreCase(serverEncodingToSet)) { + serverEncodingToSet = "Cp1252"; + } + if ("UnicodeBig".equalsIgnoreCase(serverEncodingToSet) || + "UTF-16".equalsIgnoreCase(serverEncodingToSet) || + "UTF-16LE".equalsIgnoreCase(serverEncodingToSet) || + "UTF-32".equalsIgnoreCase(serverEncodingToSet) + ) { + serverEncodingToSet = "UTF-8"; + } + + setEncoding(serverEncodingToSet); + + } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) { + if (realJavaEncoding != null) { + // user knows best, try it + setEncoding(realJavaEncoding); + } else { + throw SQLError.createSQLException( + "Unknown initial character set index '" + + this.io.serverCharsetIndex + + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + if (getEncoding() == null) { + // punt? + setEncoding("ISO8859_1"); + } + + // + // Has the user has 'forced' the character encoding via + // driver properties? + // + if (getUseUnicode()) { + if (realJavaEncoding != null) { + + // + // Now, inform the server what character set we + // will be using from now-on... + // + if (realJavaEncoding.equalsIgnoreCase("UTF-8") + || realJavaEncoding.equalsIgnoreCase("UTF8")) { + // charset names are case-sensitive + + boolean utf8mb4Supported = versionMeetsMinimum(5, 5, 2); + boolean useutf8mb4 = false; + + if (utf8mb4Supported) { + useutf8mb4 = (this.io.serverCharsetIndex == 45); + } + + if (!getUseOldUTF8Behavior()) { + if (dontCheckServerMatch || !characterSetNamesMatches("utf8") + || (utf8mb4Supported && !characterSetNamesMatches("utf8mb4"))) { + execSQL(null, "SET NAMES " + (useutf8mb4 ? "utf8mb4" : "utf8"), -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, + false, this.database, null, false); + } + } else { + execSQL(null, "SET NAMES latin1", -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, + false, this.database, null, false); + } + + setEncoding(realJavaEncoding); + } /* not utf-8 */else { + String mysqlEncodingName = CharsetMapping + .getMysqlEncodingForJavaEncoding( + realJavaEncoding + .toUpperCase(Locale.ENGLISH), + this); + + /* + * if ("koi8_ru".equals(mysqlEncodingName)) { // + * This has a _different_ name in 4.1... + * mysqlEncodingName = "ko18r"; } else if + * ("euc_kr".equals(mysqlEncodingName)) { // + * Different name in 4.1 mysqlEncodingName = + * "euckr"; } + */ + + if (mysqlEncodingName != null) { + + if (dontCheckServerMatch || !characterSetNamesMatches(mysqlEncodingName)) { + execSQL(null, "SET NAMES " + mysqlEncodingName, + -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, + false, this.database, null, false); + } + } + + // Switch driver's encoding now, since the server + // knows what we're sending... + // + setEncoding(realJavaEncoding); + } + } else if (getEncoding() != null) { + // Tell the server we'll use the server default charset + // to send our + // queries from now on.... + String mysqlEncodingName = getServerCharacterEncoding(); + + if(getUseOldUTF8Behavior()){ + mysqlEncodingName = "latin1"; + } + + boolean ucs2 = false; + if ( "ucs2".equalsIgnoreCase(mysqlEncodingName) || + "utf16".equalsIgnoreCase(mysqlEncodingName) || + "utf16le".equalsIgnoreCase(mysqlEncodingName) || + "utf32".equalsIgnoreCase(mysqlEncodingName)) { + mysqlEncodingName = "utf8"; + ucs2 = true; + if (getCharacterSetResults() == null) { + setCharacterSetResults("UTF-8"); + } + } + + if (dontCheckServerMatch || !characterSetNamesMatches(mysqlEncodingName) || ucs2) { + try { + execSQL(null, "SET NAMES " + mysqlEncodingName, -1, + null, DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + } + + realJavaEncoding = getEncoding(); + } + + } + + // + // We know how to deal with any charset coming back from + // the database, so tell the server not to do conversion + // if the user hasn't 'forced' a result-set character set + // + + String onServer = null; + boolean isNullOnServer = false; + + if (this.serverVariables != null) { + onServer = this.serverVariables.get("character_set_results"); + + isNullOnServer = onServer == null || "NULL".equalsIgnoreCase(onServer) || onServer.length() == 0; + } + + if (getCharacterSetResults() == null) { + + // + // Only send if needed, if we're caching server variables + // we -have- to send, because we don't know what it was + // before we cached them. + // + if (!isNullOnServer) { + try { + execSQL(null, "SET character_set_results = NULL", -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, + false); + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + if (!this.usingCachedConfig) { + this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, null); + } + } else { + if (!this.usingCachedConfig) { + this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, onServer); + } + } + } else { + + if(getUseOldUTF8Behavior()){ + try { + execSQL(null, "SET NAMES " + "latin1", -1, + null, DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + } + String charsetResults = getCharacterSetResults(); + String mysqlEncodingName = null; + + if ("UTF-8".equalsIgnoreCase(charsetResults) + || "UTF8".equalsIgnoreCase(charsetResults)) { + mysqlEncodingName = "utf8"; + } else if ("null".equalsIgnoreCase(charsetResults)) { + mysqlEncodingName = "NULL"; + } else { + mysqlEncodingName = CharsetMapping + .getMysqlEncodingForJavaEncoding(charsetResults + .toUpperCase(Locale.ENGLISH), this); + } + + // + // Only change the value if needed + // + + if (mysqlEncodingName == null) { + throw SQLError.createSQLException( + "Can't map "+charsetResults+" given for characterSetResults to a supported MySQL encoding.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (!mysqlEncodingName.equalsIgnoreCase( + this.serverVariables.get("character_set_results"))) { + StringBuffer setBuf = new StringBuffer( + "SET character_set_results = ".length() + + mysqlEncodingName.length()); + setBuf.append("SET character_set_results = ").append( + mysqlEncodingName); + + try { + execSQL(null, setBuf.toString(), -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + + if (!this.usingCachedConfig) { + this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, + mysqlEncodingName); + } + + // We have to set errorMessageEncoding according to new value + // of charsetResults for server version 5.5 and higher + if (versionMeetsMinimum(5, 5, 0)) { + this.errorMessageEncoding = charsetResults; + } + + } else { + if (!this.usingCachedConfig) { + this.serverVariables.put(JDBC_LOCAL_CHARACTER_SET_RESULTS, onServer); + } + } + } + + if (getConnectionCollation() != null) { + StringBuffer setBuf = new StringBuffer( + "SET collation_connection = ".length() + + getConnectionCollation().length()); + setBuf.append("SET collation_connection = ").append( + getConnectionCollation()); + + try { + execSQL(null, setBuf.toString(), -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + } + } else { + // Use what the server has specified + realJavaEncoding = getEncoding(); // so we don't get + // swapped out in the finally + // block.... + } + } finally { + // Failsafe, make sure that the driver's notion of character + // encoding matches what the user has specified. + // + setEncoding(realJavaEncoding); + } + + /** + * Check if we need a CharsetEncoder for escaping codepoints that are + * transformed to backslash (0x5c) in the connection encoding. + */ + try { + CharsetEncoder enc = Charset.forName(getEncoding()).newEncoder(); + CharBuffer cbuf = CharBuffer.allocate(1); + ByteBuffer bbuf = ByteBuffer.allocate(1); + + cbuf.put("\u00a5"); + cbuf.position(0); + enc.encode(cbuf, bbuf, true); + if(bbuf.get(0) == '\\') { + requiresEscapingEncoder = true; + } else { + cbuf.clear(); + bbuf.clear(); + + cbuf.put("\u20a9"); + cbuf.position(0); + enc.encode(cbuf, bbuf, true); + if(bbuf.get(0) == '\\') { + requiresEscapingEncoder = true; + } + } + } catch(java.nio.charset.UnsupportedCharsetException ucex) { + // fallback to String API - for Java 1.4 + try { + byte bbuf[] = StringUtils.getBytes("\u00a5", getEncoding()); + if (bbuf[0] == '\\') { + requiresEscapingEncoder = true; + } else { + bbuf = StringUtils.getBytes("\u20a9", getEncoding()); + if (bbuf[0] == '\\') { + requiresEscapingEncoder = true; + } + } + } catch(UnsupportedEncodingException ueex) { + throw SQLError.createSQLException("Unable to use encoding: " + getEncoding(), + SQLError.SQL_STATE_GENERAL_ERROR, ueex, + getExceptionInterceptor()); + } + } + + return characterSetAlreadyConfigured; + } + + /** + * Configures the client's timezone if required. + * + * @throws SQLException + * if the timezone the server is configured to use can't be + * mapped to a Java timezone. + */ + private void configureTimezone() throws SQLException { + String configuredTimeZoneOnServer = this.serverVariables.get("timezone"); + + if (configuredTimeZoneOnServer == null) { + configuredTimeZoneOnServer = this.serverVariables.get("time_zone"); + + if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) { + configuredTimeZoneOnServer = this.serverVariables.get("system_time_zone"); + } + } + + String canoncicalTimezone = getServerTimezone(); + + if ((getUseTimezone() || !getUseLegacyDatetimeCode()) && configuredTimeZoneOnServer != null) { + // user can override this with driver properties, so don't detect if that's the case + if (canoncicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canoncicalTimezone)) { + try { + canoncicalTimezone = TimeUtil + .getCanoncialTimezone(configuredTimeZoneOnServer, getExceptionInterceptor()); + + if (canoncicalTimezone == null) { + throw SQLError.createSQLException("Can't map timezone '" + + configuredTimeZoneOnServer + "' to " + + " canonical timezone.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } catch (IllegalArgumentException iae) { + throw SQLError.createSQLException(iae.getMessage(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + } else { + canoncicalTimezone = getServerTimezone(); + } + + if (canoncicalTimezone != null && canoncicalTimezone.length() > 0) { + this.serverTimezoneTZ = TimeZone.getTimeZone(canoncicalTimezone); + + // + // The Calendar class has the behavior of mapping + // unknown timezones to 'GMT' instead of throwing an + // exception, so we must check for this... + // + if (!canoncicalTimezone.equalsIgnoreCase("GMT") + && this.serverTimezoneTZ.getID().equals("GMT")) { + throw SQLError.createSQLException("No timezone mapping entry for '" + + canoncicalTimezone + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if ("GMT".equalsIgnoreCase(this.serverTimezoneTZ.getID())) { + this.isServerTzUTC = true; + } else { + this.isServerTzUTC = false; + } + } + } + + private void createInitialHistogram(long[] breakpoints, + long lowerBound, long upperBound) { + + double bucketSize = (((double) upperBound - (double) lowerBound) / HISTOGRAM_BUCKETS) * 1.25; + + if (bucketSize < 1) { + bucketSize = 1; + } + + for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { + breakpoints[i] = lowerBound; + lowerBound += bucketSize; + } + } + + /** + * Creates an IO channel to the server + * + * @param isForReconnect + * is this request for a re-connect + * @return a new MysqlIO instance connected to a server + * @throws SQLException + * if a database access error occurs + * @throws CommunicationsException + * DOCUMENT ME! + */ + public void createNewIO(boolean isForReconnect) + throws SQLException { + synchronized (getConnectionMutex()) { + // Synchronization Not needed for *new* connections, but defintely for + // connections going through fail-over, since we might get the + // new connection up and running *enough* to start sending + // cached or still-open server-side prepared statements over + // to the backend before we get a chance to re-prepare them... + + + Properties mergedProps = exposeAsProperties(this.props); + + if (!getHighAvailability()) { + connectOneTryOnly(isForReconnect, mergedProps); + + return; + } + + connectWithRetries(isForReconnect, mergedProps); + } + } + + private void connectWithRetries(boolean isForReconnect, + Properties mergedProps) throws SQLException { + double timeout = getInitialTimeout(); + boolean connectionGood = false; + + Exception connectionException = null; + + for (int attemptCount = 0; (attemptCount < getMaxReconnects()) + && !connectionGood; attemptCount++) { + try { + if (this.io != null) { + this.io.forceClose(); + } + + coreConnect(mergedProps); + pingInternal(false, 0); + + boolean oldAutoCommit; + int oldIsolationLevel; + boolean oldReadOnly; + String oldCatalog; + + synchronized (getConnectionMutex()) { + this.connectionId = this.io.getThreadId(); + this.isClosed = false; + + // save state from old connection + oldAutoCommit = getAutoCommit(); + oldIsolationLevel = this.isolationLevel; + oldReadOnly = isReadOnly(false); + oldCatalog = getCatalog(); + + this.io.setStatementInterceptors(this.statementInterceptors); + } + + // Server properties might be different + // from previous connection, so initialize + // again... + initializePropsFromServer(); + + if (isForReconnect) { + // Restore state from old connection + setAutoCommit(oldAutoCommit); + + if (this.hasIsolationLevels) { + setTransactionIsolation(oldIsolationLevel); + } + + setCatalog(oldCatalog); + setReadOnly(oldReadOnly); + } + + connectionGood = true; + + break; + } catch (Exception EEE) { + connectionException = EEE; + connectionGood = false; + } + + if (connectionGood) { + break; + } + + if (attemptCount > 0) { + try { + Thread.sleep((long) timeout * 1000); + } catch (InterruptedException IE) { + // ignore + } + } + } // end attempts for a single host + + if (!connectionGood) { + // We've really failed! + SQLException chainedEx = SQLError.createSQLException( + Messages.getString("Connection.UnableToConnectWithRetries", + new Object[] {Integer.valueOf(getMaxReconnects())}), + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, getExceptionInterceptor()); + chainedEx.initCause(connectionException); + + throw chainedEx; + } + + if (getParanoid() && !getHighAvailability()) { + this.password = null; + this.user = null; + } + + if (isForReconnect) { + // + // Retrieve any 'lost' prepared statements if re-connecting + // + Iterator statementIter = this.openStatements.values().iterator(); + + // + // We build a list of these outside the map of open statements, + // because + // in the process of re-preparing, we might end up having to + // close + // a prepared statement, thus removing it from the map, and + // generating + // a ConcurrentModificationException + // + Stack serverPreparedStatements = null; + + while (statementIter.hasNext()) { + Statement statementObj = statementIter.next(); + + if (statementObj instanceof ServerPreparedStatement) { + if (serverPreparedStatements == null) { + serverPreparedStatements = new Stack(); + } + + serverPreparedStatements.add(statementObj); + } + } + + if (serverPreparedStatements != null) { + while (!serverPreparedStatements.isEmpty()) { + ((ServerPreparedStatement) serverPreparedStatements + .pop()).rePrepare(); + } + } + } + } + + private void coreConnect(Properties mergedProps) throws SQLException, + IOException { + int newPort = 3306; + String newHost = "localhost"; + + String protocol = mergedProps.getProperty(NonRegisteringDriver.PROTOCOL_PROPERTY_KEY); + + if (protocol != null) { + // "new" style URL + + if ("tcp".equalsIgnoreCase(protocol)) { + newHost = normalizeHost(mergedProps.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY)); + newPort = parsePortNumber(mergedProps.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, "3306")); + } else if ("pipe".equalsIgnoreCase(protocol)) { + setSocketFactoryClassName(NamedPipeSocketFactory.class.getName()); + + String path = mergedProps.getProperty(NonRegisteringDriver.PATH_PROPERTY_KEY); + + if (path != null) { + mergedProps.setProperty(NamedPipeSocketFactory.NAMED_PIPE_PROP_NAME, path); + } + } else { + // normalize for all unknown protocols + newHost = normalizeHost(mergedProps.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY)); + newPort = parsePortNumber(mergedProps.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, "3306")); + } + } else { + + String[] parsedHostPortPair = NonRegisteringDriver + .parseHostPortPair(this.hostPortPair); + newHost = parsedHostPortPair[NonRegisteringDriver.HOST_NAME_INDEX]; + + newHost = normalizeHost(newHost); + + if (parsedHostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) { + newPort = parsePortNumber(parsedHostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]); + } + } + + this.port = newPort; + this.host = newHost; + + // reset max-rows to default value + this.sessionMaxRows = -1; + + this.io = new MysqlIO(newHost, newPort, + mergedProps, getSocketFactoryClassName(), + getProxy(), getSocketTimeout(), + this.largeRowSizeThreshold.getValueAsInt()); + this.io.doHandshake(this.user, this.password, + this.database); + } + + private String normalizeHost(String hostname) { + if (hostname == null || StringUtils.isEmptyOrWhitespaceOnly(hostname)) { + return "localhost"; + } + + return hostname; + } + private int parsePortNumber(String portAsString) + throws SQLException { + int portNumber = 3306; + try { + portNumber = Integer + .parseInt(portAsString); + } catch (NumberFormatException nfe) { + throw SQLError.createSQLException( + "Illegal connection port value '" + + portAsString + + "'", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor()); + } + return portNumber; + } + + private void connectOneTryOnly(boolean isForReconnect, + Properties mergedProps) throws SQLException { + Exception connectionNotEstablishedBecause = null; + + try { + + coreConnect(mergedProps); + this.connectionId = this.io.getThreadId(); + this.isClosed = false; + + // save state from old connection + boolean oldAutoCommit = getAutoCommit(); + int oldIsolationLevel = this.isolationLevel; + boolean oldReadOnly = isReadOnly(false); + String oldCatalog = getCatalog(); + + this.io.setStatementInterceptors(this.statementInterceptors); + + // Server properties might be different + // from previous connection, so initialize + // again... + initializePropsFromServer(); + + if (isForReconnect) { + // Restore state from old connection + setAutoCommit(oldAutoCommit); + + if (this.hasIsolationLevels) { + setTransactionIsolation(oldIsolationLevel); + } + + setCatalog(oldCatalog); + + setReadOnly(oldReadOnly); + } + return; + + } catch (Exception EEE) { + + if (EEE instanceof SQLException + && ((SQLException)EEE).getErrorCode() == MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD + && !getDisconnectOnExpiredPasswords()) { + return; + } + + if (this.io != null) { + this.io.forceClose(); + } + + connectionNotEstablishedBecause = EEE; + + if (EEE instanceof SQLException) { + throw (SQLException)EEE; + } + + SQLException chainedEx = SQLError.createSQLException( + Messages.getString("Connection.UnableToConnect"), + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, getExceptionInterceptor()); + chainedEx.initCause(connectionNotEstablishedBecause); + + throw chainedEx; + } + } + + private void createPreparedStatementCaches() throws SQLException { + synchronized (getConnectionMutex()) { + int cacheSize = getPreparedStatementCacheSize(); + + try { + Class factoryClass; + + factoryClass = Class.forName(getParseInfoCacheFactory()); + + @SuppressWarnings("unchecked") + CacheAdapterFactory cacheFactory = ((CacheAdapterFactory)factoryClass.newInstance()); + + this.cachedPreparedStatementParams = cacheFactory.getInstance(this, myURL, getPreparedStatementCacheSize(), getPreparedStatementCacheSqlLimit(), props); + + } catch (ClassNotFoundException e) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.CantFindCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}), + getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } catch (InstantiationException e) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}), + getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } catch (IllegalAccessException e) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}), + getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } + + if (getUseServerPreparedStmts()) { + this.serverSideStatementCheckCache = new LRUCache(cacheSize); + + this.serverSideStatementCache = new LRUCache(cacheSize) { + + private static final long serialVersionUID = 7692318650375988114L; + + protected boolean removeEldestEntry(java.util.Map.Entry eldest) { + if (this.maxElements <= 1) { + return false; + } + + boolean removeIt = super.removeEldestEntry(eldest); + + if (removeIt) { + ServerPreparedStatement ps = + (ServerPreparedStatement)eldest.getValue(); + ps.isCached = false; + ps.setClosed(false); + + try { + ps.close(); + } catch (SQLException sqlEx) { + // punt + } + } + + return removeIt; + } + }; + } + } + } + + /** + * SQL statements without parameters are normally executed using Statement + * objects. If the same SQL statement is executed many times, it is more + * efficient to use a PreparedStatement + * + * @return a new Statement object + * @throws SQLException + * passed through from the constructor + */ + public java.sql.Statement createStatement() throws SQLException { + return createStatement(DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY); + } + + /** + * JDBC 2.0 Same as createStatement() above, but allows the default result + * set type and result set concurrency type to be overridden. + * + * @param resultSetType + * a result set type, see ResultSet.TYPE_XXX + * @param resultSetConcurrency + * a concurrency type, see ResultSet.CONCUR_XXX + * @return a new Statement object + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Statement createStatement(int resultSetType, + int resultSetConcurrency) throws SQLException { + checkClosed(); + + StatementImpl stmt = new StatementImpl(getLoadBalanceSafeProxy(), this.database); + stmt.setResultSetType(resultSetType); + stmt.setResultSetConcurrency(resultSetConcurrency); + + return stmt; + } + + /** + * @see Connection#createStatement(int, int, int) + */ + public java.sql.Statement createStatement(int resultSetType, + int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + if (getPedantic()) { + if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { + throw SQLError.createSQLException( + "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return createStatement(resultSetType, resultSetConcurrency); + } + + public void dumpTestcaseQuery(String query) { + System.err.println(query); + } + + public Connection duplicate() throws SQLException { + return new ConnectionImpl( this.origHostToConnectTo, + this.origPortToConnectTo, + this.props, + this.origDatabaseToConnectTo, + this.myURL); + } + + /** + * Send a query to the server. Returns one of the ResultSet objects. This is + * synchronized, so Statement's queries will be serialized. + * + * @param callingStatement + * DOCUMENT ME! + * @param sql + * the SQL statement to be executed + * @param maxRows + * DOCUMENT ME! + * @param packet + * DOCUMENT ME! + * @param resultSetType + * DOCUMENT ME! + * @param resultSetConcurrency + * DOCUMENT ME! + * @param streamResults + * DOCUMENT ME! + * @param queryIsSelectOnly + * DOCUMENT ME! + * @param catalog + * DOCUMENT ME! + * @param unpackFields + * DOCUMENT ME! + * @return a ResultSet holding the results + * @exception SQLException + * if a database error occurs + */ + + // ResultSet execSQL(Statement callingStatement, String sql, + // int maxRowsToRetreive, String catalog) throws SQLException { + // return execSQL(callingStatement, sql, maxRowsToRetreive, null, + // java.sql.ResultSet.TYPE_FORWARD_ONLY, + // DEFAULT_RESULT_SET_CONCURRENCY, catalog); + // } + // ResultSet execSQL(Statement callingStatement, String sql, int maxRows, + // int resultSetType, int resultSetConcurrency, boolean streamResults, + // boolean queryIsSelectOnly, String catalog, boolean unpackFields) throws + // SQLException { + // return execSQL(callingStatement, sql, maxRows, null, resultSetType, + // resultSetConcurrency, streamResults, queryIsSelectOnly, catalog, + // unpackFields); + // } + public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, + Buffer packet, int resultSetType, int resultSetConcurrency, + boolean streamResults, String catalog, + Field[] cachedMetadata) throws SQLException { + return execSQL(callingStatement, sql, maxRows, packet, resultSetType, + resultSetConcurrency, streamResults, + catalog, cachedMetadata, false); + } + + public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, + Buffer packet, int resultSetType, int resultSetConcurrency, + boolean streamResults, String catalog, + Field[] cachedMetadata, + boolean isBatch) throws SQLException { + synchronized (getConnectionMutex()) { + // + // Fall-back if the master is back online if we've + // issued queriesBeforeRetryMaster queries since + // we failed over + // + + long queryStartTime = 0; + + int endOfQueryPacketPosition = 0; + + if (packet != null) { + endOfQueryPacketPosition = packet.getPosition(); + } + + if (getGatherPerformanceMetrics()) { + queryStartTime = System.currentTimeMillis(); + } + + this.lastQueryFinishedTime = 0; // we're busy! + + if ((getHighAvailability()) + && (this.autoCommit || getAutoReconnectForPools()) + && this.needsPing && !isBatch) { + try { + pingInternal(false, 0); + + this.needsPing = false; + } catch (Exception Ex) { + createNewIO(true); + } + } + + try { + if (packet == null) { + String encoding = null; + + if (getUseUnicode()) { + encoding = getEncoding(); + } + + return this.io.sqlQueryDirect(callingStatement, sql, + encoding, null, maxRows, resultSetType, + resultSetConcurrency, streamResults, catalog, + cachedMetadata); + } + + return this.io.sqlQueryDirect(callingStatement, null, null, + packet, maxRows, resultSetType, + resultSetConcurrency, streamResults, catalog, + cachedMetadata); + } catch (java.sql.SQLException sqlE) { + // don't clobber SQL exceptions + + if (getDumpQueriesOnException()) { + String extractedSql = extractSqlFromPacket(sql, packet, + endOfQueryPacketPosition); + StringBuffer messageBuf = new StringBuffer(extractedSql + .length() + 32); + messageBuf + .append("\n\nQuery being executed when exception was thrown:\n"); + messageBuf.append(extractedSql); + messageBuf.append("\n\n"); + + sqlE = appendMessageToException(sqlE, messageBuf.toString(), getExceptionInterceptor()); + } + + if ((getHighAvailability())) { + this.needsPing = true; + } else { + String sqlState = sqlE.getSQLState(); + + if ((sqlState != null) + && sqlState + .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) { + cleanup(sqlE); + } + } + + throw sqlE; + } catch (Exception ex) { + if (getHighAvailability()) { + this.needsPing = true; + } else if (ex instanceof IOException) { + cleanup(ex); + } + + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.UnexpectedException"), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; + } finally { + if (getMaintainTimeStats()) { + this.lastQueryFinishedTime = System.currentTimeMillis(); + } + + + if (getGatherPerformanceMetrics()) { + long queryTime = System.currentTimeMillis() + - queryStartTime; + + registerQueryExecutionTime(queryTime); + } + } + } + } + + public String extractSqlFromPacket(String possibleSqlQuery, + Buffer queryPacket, int endOfQueryPacketPosition) + throws SQLException { + + String extractedSql = null; + + if (possibleSqlQuery != null) { + if (possibleSqlQuery.length() > getMaxQuerySizeToLog()) { + StringBuffer truncatedQueryBuf = new StringBuffer( + possibleSqlQuery.substring(0, getMaxQuerySizeToLog())); + truncatedQueryBuf.append(Messages.getString("MysqlIO.25")); + extractedSql = truncatedQueryBuf.toString(); + } else { + extractedSql = possibleSqlQuery; + } + } + + if (extractedSql == null) { + // This is probably from a client-side prepared + // statement + + int extractPosition = endOfQueryPacketPosition; + + boolean truncated = false; + + if (endOfQueryPacketPosition > getMaxQuerySizeToLog()) { + extractPosition = getMaxQuerySizeToLog(); + truncated = true; + } + + extractedSql = StringUtils.toString(queryPacket.getByteBuffer(), 5, + (extractPosition - 5)); + + if (truncated) { + extractedSql += Messages.getString("MysqlIO.25"); //$NON-NLS-1$ + } + } + + return extractedSql; + + } + + public StringBuffer generateConnectionCommentBlock(StringBuffer buf) { + buf.append("/* conn id "); + buf.append(getId()); + buf.append(" clock: "); + buf.append(System.currentTimeMillis()); + buf.append(" */ "); + + return buf; + } + + public int getActiveStatementCount() { + // Might not have one of these if + // not tracking open resources + if (this.openStatements != null) { + synchronized (this.openStatements) { + return this.openStatements.size(); + } + } + + return 0; + } + + /** + * Gets the current auto-commit state + * + * @return Current state of auto-commit + * @exception SQLException + * if an error occurs + * @see setAutoCommit + */ + public boolean getAutoCommit() throws SQLException { + synchronized (getConnectionMutex()) { + return this.autoCommit; + } + } + + /** + * Optimization to only use one calendar per-session, or calculate it for + * each call, depending on user configuration + */ + public Calendar getCalendarInstanceForSessionOrNew() { + if (getDynamicCalendars()) { + return Calendar.getInstance(); + } + + return getSessionLockedCalendar(); + } + + /** + * Return the connections current catalog name, or null if no catalog name + * is set, or we dont support catalogs. + *

+ * Note: MySQL's notion of catalogs are individual databases. + *

+ * + * @return the current catalog name or null + * @exception SQLException + * if a database access error occurs + */ + public String getCatalog() throws SQLException { + synchronized (getConnectionMutex()) { + return this.database; + } + } + + /** + * @return Returns the characterSetMetadata. + */ + public String getCharacterSetMetadata() { + synchronized (getConnectionMutex()) { + return this.characterSetMetadata; + } + } + + /** + * Returns the locally mapped instance of a charset converter (to avoid + * overhead of static synchronization). + * + * @param javaEncodingName + * the encoding name to retrieve + * @return a character converter, or null if one couldn't be mapped. + */ + public SingleByteCharsetConverter getCharsetConverter( + String javaEncodingName) throws SQLException { + if (javaEncodingName == null) { + return null; + } + + if (this.usePlatformCharsetConverters) { + return null; // we'll use Java's built-in routines for this + // they're finally fast enough + } + + SingleByteCharsetConverter converter = null; + + synchronized (this.charsetConverterMap) { + Object asObject = this.charsetConverterMap + .get(javaEncodingName); + + if (asObject == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) { + return null; + } + + converter = (SingleByteCharsetConverter)asObject; + + if (converter == null) { + try { + converter = SingleByteCharsetConverter.getInstance( + javaEncodingName, this); + + if (converter == null) { + this.charsetConverterMap.put(javaEncodingName, + CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); + } else { + this.charsetConverterMap.put(javaEncodingName, converter); + } + } catch (UnsupportedEncodingException unsupEncEx) { + this.charsetConverterMap.put(javaEncodingName, + CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); + + converter = null; + } + } + } + + return converter; + } + + /** + * Returns the Java character encoding name for the given MySQL server + * charset index + * + * @param charsetIndex + * @return the Java character encoding name for the given MySQL server + * charset index + * @throws SQLException + * if the character set index isn't known by the driver + */ + public String getCharsetNameForIndex(int charsetIndex) + throws SQLException { + String charsetName = null; + + if (getUseOldUTF8Behavior()) { + return getEncoding(); + } + + if (charsetIndex != MysqlDefs.NO_CHARSET_INFO) { + try { + charsetName = this.indexToJavaCharset.get(charsetIndex); + // checking against static maps if no custom charset found + if (charsetName==null) charsetName = CharsetMapping.INDEX_TO_CHARSET[charsetIndex]; + + if (this.characterEncodingIsAliasForSjis) { + if ("sjis".equalsIgnoreCase(charsetName) || + "MS932".equalsIgnoreCase(charsetName) /* for JDK6 */) { + // Use our encoding so that code pages like Cp932 work + charsetName = getEncoding(); + } + } + } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) { + throw SQLError.createSQLException( + "Unknown character set index for field '" + + charsetIndex + "' received from server.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + // Punt + if (charsetName == null) { + charsetName = getEncoding(); + } + } else { + charsetName = getEncoding(); + } + + return charsetName; + } + + /** + * DOCUMENT ME! + * + * @return Returns the defaultTimeZone. + */ + public TimeZone getDefaultTimeZone() { + return this.defaultTimeZone; + } + + public String getErrorMessageEncoding() { + return errorMessageEncoding; + } + + /** + * @see Connection#getHoldability() + */ + public int getHoldability() throws SQLException { + return java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + public long getId() { + return this.connectionId; + } + + /** + * NOT JDBC-Compliant, but clients can use this method to determine how long + * this connection has been idle. This time (reported in milliseconds) is + * updated once a query has completed. + * + * @return number of ms that this connection has been idle, 0 if the driver + * is busy retrieving results. + */ + public long getIdleFor() { + synchronized (getConnectionMutex()) { + if (this.lastQueryFinishedTime == 0) { + return 0; + } + + long now = System.currentTimeMillis(); + long idleTime = now - this.lastQueryFinishedTime; + + return idleTime; + } + } + + /** + * Returns the IO channel to the server + * + * @return the IO channel to the server + * @throws SQLException + * if the connection is closed. + */ + public MysqlIO getIO() throws SQLException { + if ((this.io == null) || this.isClosed) { + throw SQLError.createSQLException( + "Operation not allowed on closed connection", + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor()); + } + + return this.io; + } + + /** + * Returns the log mechanism that should be used to log information from/for + * this Connection. + * + * @return the Log instance to use for logging messages. + * @throws SQLException + * if an error occurs + */ + public Log getLog() throws SQLException { + return this.log; + } + + public int getMaxBytesPerChar(String javaCharsetName) throws SQLException { + return getMaxBytesPerChar(null, javaCharsetName); + } + + public int getMaxBytesPerChar(Integer charsetIndex, String javaCharsetName) throws SQLException { + + String charset = null; + + try { + // if we can get it by charsetIndex just doing it + + // getting charset name from dynamic maps in connection; + // we do it before checking against static maps because custom charset on server + // can be mapped to index from our static map key's diapason + if (this.indexToCustomMysqlCharset != null) { + charset = this.indexToCustomMysqlCharset.get(charsetIndex); + } + // checking against static maps if no custom charset found + if (charset==null) charset = CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(charsetIndex); + + // if we didn't find charset name by index + if (charset == null) { + charset = CharsetMapping.getMysqlEncodingForJavaEncoding(javaCharsetName, this); + if ((this.io.serverCharsetIndex == 33) && (versionMeetsMinimum(5, 5, 3)) && (javaCharsetName.equalsIgnoreCase("UTF-8"))) { + //Avoid UTF8mb4 + charset = "utf8"; + } + } + + // checking against dynamic maps in connection + Integer mblen = null; + if (this.mysqlCharsetToCustomMblen != null) { + mblen = this.mysqlCharsetToCustomMblen.get(charset); + } + + // checking against static maps + if (mblen == null) mblen = CharsetMapping.STATIC_CHARSET_TO_NUM_BYTES_MAP.get(charset); + if (mblen == null) mblen = CharsetMapping.STATIC_4_0_CHARSET_TO_NUM_BYTES_MAP.get(charset); + + if (mblen != null) return mblen.intValue(); + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + return 1; // we don't know + } + + /** + * A connection's database is able to provide information describing its + * tables, its supported SQL grammar, its stored procedures, the + * capabilities of this connection, etc. This information is made available + * through a DatabaseMetaData object. + * + * @return a DatabaseMetaData object for this connection + * @exception SQLException + * if a database access error occurs + */ + public java.sql.DatabaseMetaData getMetaData() throws SQLException { + return getMetaData(true, true); + } + + private java.sql.DatabaseMetaData getMetaData(boolean checkClosed, boolean checkForInfoSchema) throws SQLException { + if (checkClosed) { + checkClosed(); + } + + return com.mysql.jdbc.DatabaseMetaData.getInstance(getLoadBalanceSafeProxy(), this.database, checkForInfoSchema); + } + + public java.sql.Statement getMetadataSafeStatement() throws SQLException { + java.sql.Statement stmt = createStatement(); + + if (stmt.getMaxRows() != 0) { + stmt.setMaxRows(0); + } + + stmt.setEscapeProcessing(false); + + if (stmt.getFetchSize() != 0) { + stmt.setFetchSize(0); + } + + return stmt; + } + + /** + * Returns the packet buffer size the MySQL server reported upon connection + * + * @return DOCUMENT ME! + */ + public int getNetBufferLength() { + return this.netBufferLength; + } + + /** + * Returns the server's character set + * + * @return the server's character set. + */ + public String getServerCharacterEncoding() { + if (this.io.versionMeetsMinimum(4, 1, 0)) { + String charset = null; + if (this.indexToCustomMysqlCharset != null) { + charset = this.indexToCustomMysqlCharset.get(this.io.serverCharsetIndex); + } + if (charset == null) charset = CharsetMapping.STATIC_INDEX_TO_MYSQL_CHARSET_MAP.get(this.io.serverCharsetIndex); + return charset != null ? charset : this.serverVariables.get("character_set_server"); + } + return this.serverVariables.get("character_set"); + } + + public int getServerMajorVersion() { + return this.io.getServerMajorVersion(); + } + + public int getServerMinorVersion() { + return this.io.getServerMinorVersion(); + } + + public int getServerSubMinorVersion() { + return this.io.getServerSubMinorVersion(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public TimeZone getServerTimezoneTZ() { + return this.serverTimezoneTZ; + } + + + public String getServerVariable(String variableName) { + if (this.serverVariables != null) { + return this.serverVariables.get(variableName); + } + + return null; + } + + public String getServerVersion() { + return this.io.getServerVersion(); + } + + public Calendar getSessionLockedCalendar() { + + return this.sessionCalendar; + } + + /** + * Get this Connection's current transaction isolation mode. + * + * @return the current TRANSACTION_ mode value + * @exception SQLException + * if a database access error occurs + */ + public int getTransactionIsolation() throws SQLException { + + synchronized (getConnectionMutex()) { + if (this.hasIsolationLevels && !getUseLocalSessionState()) { + java.sql.Statement stmt = null; + java.sql.ResultSet rs = null; + + try { + stmt = getMetadataSafeStatement(); + + String query = null; + + int offset = 0; + + if (versionMeetsMinimum(4, 0, 3)) { + query = "SELECT @@session.tx_isolation"; + offset = 1; + } else { + query = "SHOW VARIABLES LIKE 'transaction_isolation'"; + offset = 2; + } + + rs = stmt.executeQuery(query); + + if (rs.next()) { + String s = rs.getString(offset); + + if (s != null) { + Integer intTI = mapTransIsolationNameToValue.get(s); + + if (intTI != null) { + return intTI.intValue(); + } + } + + throw SQLError.createSQLException( + "Could not map transaction isolation '" + s + + " to a valid JDBC level.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + + throw SQLError.createSQLException( + "Could not retrieve transaction isolation level from server", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception ex) { + // ignore + ; + } + + rs = null; + } + + if (stmt != null) { + try { + stmt.close(); + } catch (Exception ex) { + // ignore + ; + } + + stmt = null; + } + } + } + + return this.isolationLevel; + } + } + + /** + * JDBC 2.0 Get the type-map object associated with this connection. By + * default, the map returned is empty. + * + * @return the type map + * @throws SQLException + * if a database error occurs + */ + public java.util.Map> getTypeMap() throws SQLException { + synchronized (getConnectionMutex()) { + if (this.typeMap == null) { + this.typeMap = new HashMap>(); + } + + return this.typeMap; + } + } + + public String getURL() { + return this.myURL; + } + + public String getUser() { + return this.user; + } + + public Calendar getUtcCalendar() { + return this.utcCalendar; + } + + /** + * The first warning reported by calls on this Connection is returned. + * Note: Sebsequent warnings will be changed to this + * java.sql.SQLWarning + * + * @return the first java.sql.SQLWarning or null + * @exception SQLException + * if a database access error occurs + */ + public SQLWarning getWarnings() throws SQLException { + return null; + } + + public boolean hasSameProperties(Connection c) { + return this.props.equals(c.getProperties()); + } + + public Properties getProperties() { + return this.props; + } + + public boolean hasTriedMaster() { + return this.hasTriedMasterFlag; + } + + public void incrementNumberOfPreparedExecutes() { + if (getGatherPerformanceMetrics()) { + this.numberOfPreparedExecutes++; + + // We need to increment this, because + // server-side prepared statements bypass + // any execution by the connection itself... + this.numberOfQueriesIssued++; + } + } + + public void incrementNumberOfPrepares() { + if (getGatherPerformanceMetrics()) { + this.numberOfPrepares++; + } + } + + public void incrementNumberOfResultSetsCreated() { + if (getGatherPerformanceMetrics()) { + this.numberOfResultSetsCreated++; + } + } + + /** + * Initializes driver properties that come from URL or properties passed to + * the driver manager. + * + * @param info + * DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + private void initializeDriverProperties(Properties info) + throws SQLException { + initializeProperties(info); + + String exceptionInterceptorClasses = getExceptionInterceptors(); + + if (exceptionInterceptorClasses != null && !"".equals(exceptionInterceptorClasses)) { + this.exceptionInterceptor = new ExceptionInterceptorChain(exceptionInterceptorClasses); + } + + this.usePlatformCharsetConverters = getUseJvmCharsetConverters(); + + this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME, getExceptionInterceptor()); + + if (getProfileSql() || getUseUsageAdvisor()) { + this.eventSink = ProfilerEventHandlerFactory.getInstance(getLoadBalanceSafeProxy()); + } + + if (getCachePreparedStatements()) { + createPreparedStatementCaches(); + } + + if (getNoDatetimeStringSync() && getUseTimezone()) { + throw SQLError.createSQLException( + "Can't enable noDatetimeStringSync and useTimezone configuration " + + "properties at the same time", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor()); + } + + if (getCacheCallableStatements()) { + this.parsedCallableStatementCache = new LRUCache( + getCallableStatementCacheSize()); + } + + if (getAllowMultiQueries()) { + setCacheResultSetMetadata(false); // we don't handle this yet + } + + if (getCacheResultSetMetadata()) { + this.resultSetMetadataCache = new LRUCache( + getMetadataCacheSize()); + } + } + + /** + * Sets varying properties that depend on server information. Called once we + * have connected to the server. + * + * @param info + * DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + private void initializePropsFromServer() throws SQLException { + String connectionInterceptorClasses = getConnectionLifecycleInterceptors(); + + this.connectionLifecycleInterceptors = null; + + if (connectionInterceptorClasses != null) { + this.connectionLifecycleInterceptors = Util.loadExtensions(this, this.props, + connectionInterceptorClasses, + "Connection.badLifecycleInterceptor", getExceptionInterceptor()); + } + + setSessionVariables(); + + // + // the "boolean" type didn't come along until MySQL-4.1 + // + + if (!versionMeetsMinimum(4, 1, 0)) { + setTransformedBitIsBoolean(false); + } + + this.parserKnowsUnicode = versionMeetsMinimum(4, 1, 0); + + // + // Users can turn off detection of server-side prepared statements + // + if (getUseServerPreparedStmts() && versionMeetsMinimum(4, 1, 0)) { + this.useServerPreparedStmts = true; + + if (versionMeetsMinimum(5, 0, 0) && !versionMeetsMinimum(5, 0, 3)) { + this.useServerPreparedStmts = false; // 4.1.2+ style prepared + // statements + // don't work on these versions + } + } + + // + // If version is greater than 3.21.22 get the server + // variables. + if (versionMeetsMinimum(3, 21, 22)) { + loadServerVariables(); + + if (versionMeetsMinimum(5, 0, 2)) { + this.autoIncrementIncrement = getServerVariableAsInt("auto_increment_increment", 1); + } else { + this.autoIncrementIncrement = 1; + } + + buildCollationMapping(); + + LicenseConfiguration.checkLicenseType(this.serverVariables); + + String lowerCaseTables = this.serverVariables.get("lower_case_table_names"); + + this.lowerCaseTableNames = "on".equalsIgnoreCase(lowerCaseTables) + || "1".equalsIgnoreCase(lowerCaseTables) + || "2".equalsIgnoreCase(lowerCaseTables); + + this.storesLowerCaseTableName = "1".equalsIgnoreCase(lowerCaseTables) || + "on".equalsIgnoreCase(lowerCaseTables); + + configureTimezone(); + + if (this.serverVariables.containsKey("max_allowed_packet")) { + int serverMaxAllowedPacket = getServerVariableAsInt("max_allowed_packet", -1); + // use server value if maxAllowedPacket hasn't been given, or max_allowed_packet is smaller + if (serverMaxAllowedPacket != -1 && (serverMaxAllowedPacket < getMaxAllowedPacket() || + getMaxAllowedPacket() <= 0)) + setMaxAllowedPacket(serverMaxAllowedPacket); + else if (serverMaxAllowedPacket == -1 && getMaxAllowedPacket() == -1) + setMaxAllowedPacket(65535); + + if (getUseServerPrepStmts()) { + int preferredBlobSendChunkSize = getBlobSendChunkSize(); + + // LONG_DATA and MySQLIO packet header size + int packetHeaderSize = ServerPreparedStatement.BLOB_STREAM_READ_BUF_SIZE + 11; + int allowedBlobSendChunkSize = Math.min(preferredBlobSendChunkSize, getMaxAllowedPacket()) + - packetHeaderSize; + + if (allowedBlobSendChunkSize <= 0) { + throw SQLError.createSQLException("Connection setting too low for 'maxAllowedPacket'. " + + "When 'useServerPrepStmts=true', 'maxAllowedPacket' must be higher than " + + packetHeaderSize + ". Check also 'max_allowed_packet' in MySQL configuration files.", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, getExceptionInterceptor()); + } + + setBlobSendChunkSize(String.valueOf(allowedBlobSendChunkSize)); + } + } + + if (this.serverVariables.containsKey("net_buffer_length")) { + this.netBufferLength = getServerVariableAsInt("net_buffer_length", 16 * 1024); + } + + checkTransactionIsolationLevel(); + + if (!versionMeetsMinimum(4, 1, 0)) { + checkServerEncoding(); + } + + this.io.checkForCharsetMismatch(); + + if (this.serverVariables.containsKey("sql_mode")) { + int sqlMode = 0; + + String sqlModeAsString = this.serverVariables.get("sql_mode"); + try { + sqlMode = Integer.parseInt(sqlModeAsString); + } catch (NumberFormatException nfe) { + // newer versions of the server has this as a string-y + // list... + sqlMode = 0; + + if (sqlModeAsString != null) { + if (sqlModeAsString.indexOf("ANSI_QUOTES") != -1) { + sqlMode |= 4; + } + + if (sqlModeAsString.indexOf("NO_BACKSLASH_ESCAPES") != -1) { + this.noBackslashEscapes = true; + } + } + } + + if ((sqlMode & 4) > 0) { + this.useAnsiQuotes = true; + } else { + this.useAnsiQuotes = false; + } + } + } + + try { + this.errorMessageEncoding = + CharsetMapping.getCharacterEncodingForErrorMessages(this); + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + + boolean overrideDefaultAutocommit = isAutoCommitNonDefaultOnServer(); + + configureClientCharacterSet(false); + + if (versionMeetsMinimum(3, 23, 15)) { + this.transactionsSupported = true; + + if (!overrideDefaultAutocommit) { + try { + setAutoCommit(true); // to override anything + // the server is set to...reqd + // by JDBC spec. + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + } + } else { + this.transactionsSupported = false; + } + + + if (versionMeetsMinimum(3, 23, 36)) { + this.hasIsolationLevels = true; + } else { + this.hasIsolationLevels = false; + } + + this.hasQuotedIdentifiers = versionMeetsMinimum(3, 23, 6); + + this.io.resetMaxBuf(); + + // + // If we're using MySQL 4.1.0 or newer, we need to figure + // out what character set metadata will be returned in, + // and then map that to a Java encoding name. + // + // We've already set it, and it might be different than what + // was originally on the server, which is why we use the + // "special" key to retrieve it + if (this.io.versionMeetsMinimum(4, 1, 0)) { + String characterSetResultsOnServerMysql = this.serverVariables.get(JDBC_LOCAL_CHARACTER_SET_RESULTS); + + if (characterSetResultsOnServerMysql == null + || StringUtils.startsWithIgnoreCaseAndWs( + characterSetResultsOnServerMysql, "NULL") + || characterSetResultsOnServerMysql.length() == 0) { + String defaultMetadataCharsetMysql = this.serverVariables.get("character_set_system"); + String defaultMetadataCharset = null; + + if (defaultMetadataCharsetMysql != null) { + defaultMetadataCharset = getJavaEncodingForMysqlEncoding(defaultMetadataCharsetMysql); + } else { + defaultMetadataCharset = "UTF-8"; + } + + this.characterSetMetadata = defaultMetadataCharset; + } else { + this.characterSetResultsOnServer = getJavaEncodingForMysqlEncoding(characterSetResultsOnServerMysql); + this.characterSetMetadata = this.characterSetResultsOnServer; + } + } else { + this.characterSetMetadata = getEncoding(); + } + + // + // Query cache is broken wrt. multi-statements before MySQL-4.1.10 + // + + if (versionMeetsMinimum(4, 1, 0) + && !this.versionMeetsMinimum(4, 1, 10) + && getAllowMultiQueries()) { + if (isQueryCacheEnabled()) { + setAllowMultiQueries(false); + } + } + + if (versionMeetsMinimum(5, 0, 0) && + (getUseLocalTransactionState() || getElideSetAutoCommits()) && + isQueryCacheEnabled() && !versionMeetsMinimum(6, 0, 10)) { + // Can't trust the server status flag on the wire if query cache is enabled, + // due to Bug#36326 + setUseLocalTransactionState(false); + setElideSetAutoCommits(false); + } + + // + // Server can do this more efficiently for us + // + + setupServerForTruncationChecks(); + } + + private boolean isQueryCacheEnabled() { + return "ON".equalsIgnoreCase(this.serverVariables.get("query_cache_type")) + && !"0".equalsIgnoreCase(this.serverVariables.get("query_cache_size")); + } + + private int getServerVariableAsInt(String variableName, int fallbackValue) + throws SQLException { + try { + return Integer.parseInt(this.serverVariables.get(variableName)); + } catch (NumberFormatException nfe) { + getLog().logWarn(Messages.getString("Connection.BadValueInServerVariables", new Object[] {variableName, + this.serverVariables.get(variableName), Integer.valueOf(fallbackValue)})); + + return fallbackValue; + } + } + + /** + * Has the default autocommit value of 0 been changed on the server + * via init_connect? + * + * @return true if autocommit is not the default of '0' on the server. + * + * @throws SQLException + */ + private boolean isAutoCommitNonDefaultOnServer() throws SQLException { + boolean overrideDefaultAutocommit = false; + + String initConnectValue = this.serverVariables.get("init_connect"); + + if (versionMeetsMinimum(4, 1, 2) && initConnectValue != null + && initConnectValue.length() > 0) { + if (!getElideSetAutoCommits()) { + // auto-commit might have changed + java.sql.ResultSet rs = null; + java.sql.Statement stmt = null; + + try { + stmt = getMetadataSafeStatement(); + + rs = stmt.executeQuery("SELECT @@session.autocommit"); + + if (rs.next()) { + this.autoCommit = rs.getBoolean(1); + if (this.autoCommit != true) { + overrideDefaultAutocommit = true; + } + } + + } finally { + if (rs != null) { + try { + rs.close(); + } catch (SQLException sqlEx) { + // do nothing + } + } + + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException sqlEx) { + // do nothing + } + } + } + } else { + if (this.getIO().isSetNeededForAutoCommitMode(true)) { + // we're not in standard autocommit=true mode + this.autoCommit = false; + overrideDefaultAutocommit = true; + } + } + } + + return overrideDefaultAutocommit; + } + + public boolean isClientTzUTC() { + return this.isClientTzUTC; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isClosed() { + return this.isClosed; + } + + public boolean isCursorFetchEnabled() throws SQLException { + return (versionMeetsMinimum(5, 0, 2) && getUseCursorFetch()); + } + + public boolean isInGlobalTx() { + return this.isInGlobalTx; + } + + /** + * Is this connection connected to the first host in the list if + * there is a list of servers in the URL? + * + * @return true if this connection is connected to the first in + * the list. + */ + public boolean isMasterConnection() { + synchronized (getConnectionMutex()) { + return false; // handled higher up + } + } + + /** + * Is the server in a sql_mode that doesn't allow us to use \\ to escape + * things? + * + * @return Returns the noBackslashEscapes. + */ + public boolean isNoBackslashEscapesSet() { + return this.noBackslashEscapes; + } + + public boolean isReadInfoMsgEnabled() { + return this.readInfoMsg; + } + + /** + * Tests to see if the connection is in Read Only Mode. Note that prior to 5.6, + * we cannot really put the database in read only mode, but we pretend we can by + * returning the value of the readOnly flag + * + * @return true if the connection is read only + * @exception SQLException if a database access error occurs + */ + public boolean isReadOnly() throws SQLException { + return isReadOnly(true); + } + + /** + * Tests to see if the connection is in Read Only Mode. Note that prior to 5.6, + * we cannot really put the database in read only mode, but we pretend we can by + * returning the value of the readOnly flag + * + * @param useSessionStatus in some cases, for example when restoring connection with autoReconnect=true, + * we can rely only on saved readOnly state, so use useSessionStatus=false in that case + * + * @return true if the connection is read only + * @exception SQLException if a database access error occurs + */ + public boolean isReadOnly(boolean useSessionStatus) throws SQLException { + if (useSessionStatus && !this.isClosed && versionMeetsMinimum(5, 6, 5) && !getUseLocalSessionState()) { + java.sql.Statement stmt = null; + java.sql.ResultSet rs = null; + + try { + try { + stmt = getMetadataSafeStatement(); + + rs = stmt.executeQuery("select @@session.tx_read_only"); + if (rs.next()) { + return rs.getInt(1) != 0; // mysql has a habit of tri+ state booleans + } + } catch (SQLException ex1) { + if (ex1.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw SQLError.createSQLException( + "Could not retrieve transation read-only status server", + SQLError.SQL_STATE_GENERAL_ERROR, ex1, getExceptionInterceptor()); + } + } + + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception ex) { + // ignore + } + + rs = null; + } + + if (stmt != null) { + try { + stmt.close(); + } catch (Exception ex) { + // ignore + } + + stmt = null; + } + } + } + + return this.readOnly; + } + + public boolean isRunningOnJDK13() { + return this.isRunningOnJDK13; + } + + public boolean isSameResource(Connection otherConnection) { + synchronized (getConnectionMutex()) { + if (otherConnection == null) { + return false; + } + + boolean directCompare = true; + + String otherHost = ((ConnectionImpl)otherConnection).origHostToConnectTo; + String otherOrigDatabase = ((ConnectionImpl)otherConnection).origDatabaseToConnectTo; + String otherCurrentCatalog = ((ConnectionImpl)otherConnection).database; + + if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) { + directCompare = false; + } else if (otherHost != null && otherHost.indexOf(',') == -1 && + otherHost.indexOf(':') == -1) { + // need to check port numbers + directCompare = (((ConnectionImpl)otherConnection).origPortToConnectTo == + this.origPortToConnectTo); + } + + if (directCompare) { + if (!nullSafeCompare(otherOrigDatabase, this.origDatabaseToConnectTo) + || !nullSafeCompare(otherCurrentCatalog, this.database)) { + directCompare = false; + } + } + + if (directCompare) { + return true; + } + + // Has the user explicitly set a resourceId? + String otherResourceId = ((ConnectionImpl)otherConnection).getResourceId(); + String myResourceId = getResourceId(); + + if (otherResourceId != null || myResourceId != null) { + directCompare = nullSafeCompare(otherResourceId, myResourceId); + + if (directCompare) { + return true; + } + } + + return false; + } + } + + public boolean isServerTzUTC() { + return this.isServerTzUTC; + } + + + private boolean usingCachedConfig = false; + + private void createConfigCacheIfNeeded() throws SQLException { + synchronized (getConnectionMutex()) { + if (this.serverConfigCache != null) { + return; + } + + try { + Class factoryClass; + + factoryClass = Class.forName(getServerConfigCacheFactory()); + + @SuppressWarnings("unchecked") + CacheAdapterFactory> cacheFactory = ((CacheAdapterFactory>)factoryClass.newInstance()); + + this.serverConfigCache = cacheFactory.getInstance(this, myURL, Integer.MAX_VALUE, Integer.MAX_VALUE, props); + + ExceptionInterceptor evictOnCommsError = new ExceptionInterceptor() { + + public void init(Connection conn, Properties config) + throws SQLException { + } + + public void destroy() { + } + + @SuppressWarnings("synthetic-access") + public SQLException interceptException(SQLException sqlEx, + Connection conn) { + if (sqlEx.getSQLState() != null && sqlEx.getSQLState().startsWith("08")) { + serverConfigCache.invalidate(getURL()); + } + return null; + }}; + + if (this.exceptionInterceptor == null) { + this.exceptionInterceptor = evictOnCommsError; + } else { + ((ExceptionInterceptorChain)this.exceptionInterceptor).addRingZero(evictOnCommsError); + } + } catch (ClassNotFoundException e) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.CantFindCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}), + getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } catch (InstantiationException e) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}), + getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } catch (IllegalAccessException e) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.CantLoadCacheFactory", new Object[] {getParseInfoCacheFactory(), "parseInfoCacheFactory"}), + getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } + } + } + + private final static String SERVER_VERSION_STRING_VAR_NAME = "server_version_string"; + + /** + * Loads the result of 'SHOW VARIABLES' into the serverVariables field so + * that the driver can configure itself. + * + * @throws SQLException + * if the 'SHOW VARIABLES' query fails for any reason. + */ + private void loadServerVariables() throws SQLException { + + if (getCacheServerConfiguration()) { + createConfigCacheIfNeeded(); + + Map cachedVariableMap = serverConfigCache.get(getURL()); + + if (cachedVariableMap != null) { + String cachedServerVersion = cachedVariableMap.get(SERVER_VERSION_STRING_VAR_NAME); + + if (cachedServerVersion != null && this.io.getServerVersion() != null + && cachedServerVersion.equals(this.io.getServerVersion())) { + this.serverVariables = cachedVariableMap; + this.usingCachedConfig = true; + + return; + } + + serverConfigCache.invalidate(getURL()); + } + } + + java.sql.Statement stmt = null; + java.sql.ResultSet results = null; + + try { + stmt = getMetadataSafeStatement(); + + String version = this.dbmd.getDriverVersion(); + + if (version != null && version.indexOf('*') != -1) { + StringBuffer buf = new StringBuffer(version.length() + 10); + + for (int i = 0; i < version.length(); i++) { + char c = version.charAt(i); + + if (c == '*') { + buf.append("[star]"); + } else { + buf.append(c); + } + } + + version = buf.toString(); + } + + String versionComment = (this.getParanoid() || version == null) ? "" + : "/* " + version + " */"; + + String query = versionComment + "SHOW VARIABLES"; + + if (versionMeetsMinimum(5, 0, 3)) { + query = versionComment + "SHOW VARIABLES WHERE Variable_name ='language'" + + " OR Variable_name = 'net_write_timeout'" + + " OR Variable_name = 'interactive_timeout'" + + " OR Variable_name = 'wait_timeout'" + + " OR Variable_name = 'character_set_client'" + + " OR Variable_name = 'character_set_connection'" + + " OR Variable_name = 'character_set'" + + " OR Variable_name = 'character_set_server'" + + " OR Variable_name = 'tx_isolation'" + + " OR Variable_name = 'transaction_isolation'" + + " OR Variable_name = 'character_set_results'" + + " OR Variable_name = 'timezone'" + + " OR Variable_name = 'time_zone'" + + " OR Variable_name = 'system_time_zone'" + + " OR Variable_name = 'lower_case_table_names'" + + " OR Variable_name = 'max_allowed_packet'" + + " OR Variable_name = 'net_buffer_length'" + + " OR Variable_name = 'sql_mode'" + + " OR Variable_name = 'query_cache_type'" + + " OR Variable_name = 'query_cache_size'" + + " OR Variable_name = 'init_connect'"; + } + + this.serverVariables = new HashMap(); + + try { + results = stmt.executeQuery(query); + + while (results.next()) { + this.serverVariables.put(results.getString(1), results + .getString(2)); + } + + results.close(); + results = null; + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + + if (versionMeetsMinimum(5, 0, 2)) { + try { + results = stmt.executeQuery(versionComment + "SELECT @@session.auto_increment_increment"); + + if (results.next()) { + this.serverVariables.put("auto_increment_increment", results.getString(1)); + } + } catch (SQLException ex) { + if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) { + throw ex; + } + } + } + + if (getCacheServerConfiguration()) { + this.serverVariables.put(SERVER_VERSION_STRING_VAR_NAME, this.io.getServerVersion()); + + serverConfigCache.put(getURL(), this.serverVariables); + + this.usingCachedConfig = true; + } + } catch (SQLException e) { + throw e; + } finally { + if (results != null) { + try { + results.close(); + } catch (SQLException sqlE) { + ; + } + } + + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException sqlE) { + ; + } + } + } + } + + private int autoIncrementIncrement = 0; + + public int getAutoIncrementIncrement() { + return this.autoIncrementIncrement; + } + + /** + * Is the server configured to use lower-case table names only? + * + * @return true if lower_case_table_names is 'on' + */ + public boolean lowerCaseTableNames() { + return this.lowerCaseTableNames; + } + + /** + * A driver may convert the JDBC sql grammar into its system's native SQL + * grammar prior to sending it; nativeSQL returns the native form of the + * statement that the driver would have sent. + * + * @param sql + * a SQL statement that may contain one or more '?' parameter + * placeholders + * @return the native form of this statement + * @exception SQLException + * if a database access error occurs + */ + public String nativeSQL(String sql) throws SQLException { + if (sql == null) { + return null; + } + + Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, + serverSupportsConvertFn(), + getLoadBalanceSafeProxy()); + + if (escapedSqlResult instanceof String) { + return (String) escapedSqlResult; + } + + return ((EscapeProcessorResult) escapedSqlResult).escapedSql; + } + + private CallableStatement parseCallableStatement(String sql) + throws SQLException { + Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, + serverSupportsConvertFn(), getLoadBalanceSafeProxy()); + + boolean isFunctionCall = false; + String parsedSql = null; + + if (escapedSqlResult instanceof EscapeProcessorResult) { + parsedSql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; + isFunctionCall = ((EscapeProcessorResult) escapedSqlResult).callingStoredFunction; + } else { + parsedSql = (String) escapedSqlResult; + isFunctionCall = false; + } + + return CallableStatement.getInstance(getLoadBalanceSafeProxy(), parsedSql, this.database, + isFunctionCall); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean parserKnowsUnicode() { + return this.parserKnowsUnicode; + } + + /** + * Detect if the connection is still good + * + * @throws SQLException + * if the ping fails + */ + public void ping() throws SQLException { + pingInternal(true, 0); + } + + public void pingInternal(boolean checkForClosedConnection, int timeoutMillis) + throws SQLException { + if (checkForClosedConnection) { + checkClosed(); + } + + long pingMillisLifetime = getSelfDestructOnPingSecondsLifetime(); + int pingMaxOperations = getSelfDestructOnPingMaxOperations(); + + if ((pingMillisLifetime > 0 && (System.currentTimeMillis() - this.connectionCreationTimeMillis) > pingMillisLifetime) + || (pingMaxOperations > 0 && pingMaxOperations <= this.io + .getCommandCount())) { + + close(); + + throw SQLError.createSQLException(Messages + .getString("Connection.exceededConnectionLifetime"), + SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, getExceptionInterceptor()); + } + // Need MySQL-3.22.1, but who uses anything older!? + this.io.sendCommand(MysqlDefs.PING, null, null, false, null, timeoutMillis); + } + + /** + * DOCUMENT ME! + * + * @param sql + * DOCUMENT ME! + * @return DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + public java.sql.CallableStatement prepareCall(String sql) + throws SQLException { + + return prepareCall(sql, DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY); + } + + /** + * JDBC 2.0 Same as prepareCall() above, but allows the default result set + * type and result set concurrency type to be overridden. + * + * @param sql + * the SQL representing the callable statement + * @param resultSetType + * a result set type, see ResultSet.TYPE_XXX + * @param resultSetConcurrency + * a concurrency type, see ResultSet.CONCUR_XXX + * @return a new CallableStatement object containing the pre-compiled SQL + * statement + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.CallableStatement prepareCall(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + if (versionMeetsMinimum(5, 0, 0)) { + CallableStatement cStmt = null; + + if (!getCacheCallableStatements()) { + + cStmt = parseCallableStatement(sql); + } else { + synchronized (this.parsedCallableStatementCache) { + CompoundCacheKey key = new CompoundCacheKey(getCatalog(), sql); + + CallableStatement.CallableStatementParamInfo cachedParamInfo = (CallableStatement.CallableStatementParamInfo) this.parsedCallableStatementCache + .get(key); + + if (cachedParamInfo != null) { + cStmt = CallableStatement.getInstance(getLoadBalanceSafeProxy(), cachedParamInfo); + } else { + cStmt = parseCallableStatement(sql); + + synchronized (cStmt) { + cachedParamInfo = cStmt.paramInfo; + } + + this.parsedCallableStatementCache.put(key, cachedParamInfo); + } + } + } + + cStmt.setResultSetType(resultSetType); + cStmt.setResultSetConcurrency(resultSetConcurrency); + + return cStmt; + } + + throw SQLError.createSQLException("Callable statements not " + "supported.", + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); + } + + /** + * @see Connection#prepareCall(String, int, int, int) + */ + public java.sql.CallableStatement prepareCall(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + if (getPedantic()) { + if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { + throw SQLError.createSQLException( + "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + CallableStatement cStmt = (com.mysql.jdbc.CallableStatement) prepareCall( + sql, resultSetType, resultSetConcurrency); + + return cStmt; + } + + /** + * A SQL statement with or without IN parameters can be pre-compiled and + * stored in a PreparedStatement object. This object can then be used to + * efficiently execute this statement multiple times. + *

+ * Note: This method is optimized for handling parametric SQL + * statements that benefit from precompilation if the driver supports + * precompilation. In this case, the statement is not sent to the database + * until the PreparedStatement is executed. This has no direct effect on + * users; however it does affect which method throws certain + * java.sql.SQLExceptions + *

+ *

+ * MySQL does not support precompilation of statements, so they are handled + * by the driver. + *

+ * + * @param sql + * a SQL statement that may contain one or more '?' IN parameter + * placeholders + * @return a new PreparedStatement object containing the pre-compiled + * statement. + * @exception SQLException + * if a database access error occurs. + */ + public java.sql.PreparedStatement prepareStatement(String sql) + throws SQLException { + return prepareStatement(sql, DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY); + } + + /** + * @see Connection#prepareStatement(String, int) + */ + public java.sql.PreparedStatement prepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + java.sql.PreparedStatement pStmt = prepareStatement(sql); + + ((com.mysql.jdbc.PreparedStatement) pStmt) + .setRetrieveGeneratedKeys(autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS); + + return pStmt; + } + + /** + * JDBC 2.0 Same as prepareStatement() above, but allows the default result + * set type and result set concurrency type to be overridden. + * + * @param sql + * the SQL query containing place holders + * @param resultSetType + * a result set type, see ResultSet.TYPE_XXX + * @param resultSetConcurrency + * a concurrency type, see ResultSet.CONCUR_XXX + * @return a new PreparedStatement object containing the pre-compiled SQL + * statement + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.PreparedStatement prepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + // + // FIXME: Create warnings if can't create results of the given + // type or concurrency + // + PreparedStatement pStmt = null; + + boolean canServerPrepare = true; + + String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; + + if (this.useServerPreparedStmts && getEmulateUnsupportedPstmts()) { + canServerPrepare = canHandleAsServerPreparedStatement(nativeSql); + } + + if (this.useServerPreparedStmts && canServerPrepare) { + if (this.getCachePreparedStatements()) { + synchronized (this.serverSideStatementCache) { + pStmt = (com.mysql.jdbc.ServerPreparedStatement)this.serverSideStatementCache.remove(sql); + + if (pStmt != null) { + ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false); + pStmt.clearParameters(); + } + + if (pStmt == null) { + try { + pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, + this.database, resultSetType, resultSetConcurrency); + if (sql.length() < getPreparedStatementCacheSqlLimit()) { + ((com.mysql.jdbc.ServerPreparedStatement)pStmt).isCached = true; + } + + pStmt.setResultSetType(resultSetType); + pStmt.setResultSetConcurrency(resultSetConcurrency); + } catch (SQLException sqlEx) { + // Punt, if necessary + if (getEmulateUnsupportedPstmts()) { + pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); + + if (sql.length() < getPreparedStatementCacheSqlLimit()) { + this.serverSideStatementCheckCache.put(sql, Boolean.FALSE); + } + } else { + throw sqlEx; + } + } + } + } + } else { + try { + pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, + this.database, resultSetType, resultSetConcurrency); + + pStmt.setResultSetType(resultSetType); + pStmt.setResultSetConcurrency(resultSetConcurrency); + } catch (SQLException sqlEx) { + // Punt, if necessary + if (getEmulateUnsupportedPstmts()) { + pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); + } else { + throw sqlEx; + } + } + } + } else { + pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false); + } + + return pStmt; + } + } + + /** + * @see Connection#prepareStatement(String, int, int, int) + */ + public java.sql.PreparedStatement prepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + if (getPedantic()) { + if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { + throw SQLError.createSQLException( + "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + /** + * @see Connection#prepareStatement(String, int[]) + */ + public java.sql.PreparedStatement prepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + java.sql.PreparedStatement pStmt = prepareStatement(sql); + + ((com.mysql.jdbc.PreparedStatement) pStmt) + .setRetrieveGeneratedKeys((autoGenKeyIndexes != null) + && (autoGenKeyIndexes.length > 0)); + + return pStmt; + } + + /** + * @see Connection#prepareStatement(String, String[]) + */ + public java.sql.PreparedStatement prepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + java.sql.PreparedStatement pStmt = prepareStatement(sql); + + ((com.mysql.jdbc.PreparedStatement) pStmt) + .setRetrieveGeneratedKeys((autoGenKeyColNames != null) + && (autoGenKeyColNames.length > 0)); + + return pStmt; + } + + /** + * Closes connection and frees resources. + * + * @param calledExplicitly + * is this being called from close() + * @param issueRollback + * should a rollback() be issued? + * @throws SQLException + * if an error occurs + */ + public void realClose(boolean calledExplicitly, boolean issueRollback, + boolean skipLocalTeardown, Throwable reason) throws SQLException { + SQLException sqlEx = null; + + if (this.isClosed()) { + return; + } + + this.forceClosedReason = reason; + + try { + if (!skipLocalTeardown) { + if (!getAutoCommit() && issueRollback) { + try { + rollback(); + } catch (SQLException ex) { + sqlEx = ex; + } + } + + reportMetrics(); + + if (getUseUsageAdvisor()) { + if (!calledExplicitly) { + String message = "Connection implicitly closed by Driver. You should call Connection.close() from your code to free resources more efficiently and avoid resource leaks."; + + this.eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$ + this.getCatalog(), this.getId(), -1, -1, System + .currentTimeMillis(), 0, Constants.MILLIS_I18N, + null, + this.pointOfOrigin, message)); + } + + long connectionLifeTime = System.currentTimeMillis() + - this.connectionCreationTimeMillis; + + if (connectionLifeTime < 500) { + String message = "Connection lifetime of < .5 seconds. You might be un-necessarily creating short-lived connections and should investigate connection pooling to be more efficient."; + + this.eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$ + this.getCatalog(), this.getId(), -1, -1, System + .currentTimeMillis(), 0, Constants.MILLIS_I18N, + null, + this.pointOfOrigin, message)); + } + } + + try { + closeAllOpenStatements(); + } catch (SQLException ex) { + sqlEx = ex; + } + + if (this.io != null) { + try { + this.io.quit(); + } catch (Exception e) { + ; + } + + } + } else { + this.io.forceClose(); + } + + if (this.statementInterceptors != null) { + for (int i = 0; i < this.statementInterceptors.size(); i++) { + this.statementInterceptors.get(i).destroy(); + } + } + + if (this.exceptionInterceptor != null) { + this.exceptionInterceptor.destroy(); + } + } finally { + this.openStatements = null; + if (this.io != null) { + this.io.releaseResources(); + this.io = null; + } + this.statementInterceptors = null; + this.exceptionInterceptor = null; + ProfilerEventHandlerFactory.removeInstance(this); + + synchronized (getConnectionMutex()) { + if (this.cancelTimer != null) { + this.cancelTimer.cancel(); + } + } + + this.isClosed = true; + } + + if (sqlEx != null) { + throw sqlEx; + } + + } + + public void recachePreparedStatement(ServerPreparedStatement pstmt) throws SQLException { + synchronized (getConnectionMutex()) { + if (pstmt.isPoolable()) { + synchronized (this.serverSideStatementCache) { + this.serverSideStatementCache.put(pstmt.originalSql, pstmt); + } + } + } + } + + public void decachePreparedStatement(ServerPreparedStatement pstmt) throws SQLException { + synchronized (getConnectionMutex()) { + if (pstmt.isPoolable()) { + synchronized (this.serverSideStatementCache) { + this.serverSideStatementCache.remove(pstmt.originalSql); + } + } + } + } + + /** + * DOCUMENT ME! + * + * @param queryTimeMs + */ + public void registerQueryExecutionTime(long queryTimeMs) { + if (queryTimeMs > this.longestQueryTimeMs) { + this.longestQueryTimeMs = queryTimeMs; + + repartitionPerformanceHistogram(); + } + + addToPerformanceHistogram(queryTimeMs, 1); + + if (queryTimeMs < this.shortestQueryTimeMs) { + this.shortestQueryTimeMs = (queryTimeMs == 0) ? 1 : queryTimeMs; + } + + this.numberOfQueriesIssued++; + + this.totalQueryTimeMs += queryTimeMs; + } + + /** + * Register a Statement instance as open. + * + * @param stmt + * the Statement instance to remove + */ + public void registerStatement(Statement stmt) { + synchronized (this.openStatements) { + this.openStatements.put(stmt, stmt); + } + } + + /** + * @see Connection#releaseSavepoint(Savepoint) + */ + public void releaseSavepoint(Savepoint arg0) throws SQLException { + // this is a no-op + } + + private void repartitionHistogram(int[] histCounts, long[] histBreakpoints, + long currentLowerBound, long currentUpperBound) { + + if (oldHistCounts == null) { + oldHistCounts = new int[histCounts.length]; + oldHistBreakpoints = new long[histBreakpoints.length]; + } + + System.arraycopy(histCounts, 0, oldHistCounts, 0, histCounts.length); + + System.arraycopy(histBreakpoints, 0, oldHistBreakpoints, 0, + histBreakpoints.length); + + createInitialHistogram(histBreakpoints, currentLowerBound, + currentUpperBound); + + for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { + addToHistogram(histCounts, histBreakpoints, oldHistBreakpoints[i], + oldHistCounts[i], currentLowerBound, currentUpperBound); + } + } + + private void repartitionPerformanceHistogram() { + checkAndCreatePerformanceHistogram(); + + repartitionHistogram(this.perfMetricsHistCounts, + this.perfMetricsHistBreakpoints, + this.shortestQueryTimeMs == Long.MAX_VALUE ? 0 + : this.shortestQueryTimeMs, this.longestQueryTimeMs); + } + + private void repartitionTablesAccessedHistogram() { + checkAndCreateTablesAccessedHistogram(); + + repartitionHistogram(this.numTablesMetricsHistCounts, + this.numTablesMetricsHistBreakpoints, + this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0 + : this.minimumNumberTablesAccessed, + this.maximumNumberTablesAccessed); + } + + private void reportMetrics() { + if (getGatherPerformanceMetrics()) { + StringBuffer logMessage = new StringBuffer(256); + + logMessage.append("** Performance Metrics Report **\n"); + logMessage.append("\nLongest reported query: " + + this.longestQueryTimeMs + " ms"); + logMessage.append("\nShortest reported query: " + + this.shortestQueryTimeMs + " ms"); + logMessage + .append("\nAverage query execution time: " + + (this.totalQueryTimeMs / this.numberOfQueriesIssued) + + " ms"); + logMessage.append("\nNumber of statements executed: " + + this.numberOfQueriesIssued); + logMessage.append("\nNumber of result sets created: " + + this.numberOfResultSetsCreated); + logMessage.append("\nNumber of statements prepared: " + + this.numberOfPrepares); + logMessage.append("\nNumber of prepared statement executions: " + + this.numberOfPreparedExecutes); + + if (this.perfMetricsHistBreakpoints != null) { + logMessage.append("\n\n\tTiming Histogram:\n"); + int maxNumPoints = 20; + int highestCount = Integer.MIN_VALUE; + + for (int i = 0; i < (HISTOGRAM_BUCKETS); i++) { + if (this.perfMetricsHistCounts[i] > highestCount) { + highestCount = this.perfMetricsHistCounts[i]; + } + } + + if (highestCount == 0) { + highestCount = 1; // avoid DIV/0 + } + + for (int i = 0; i < (HISTOGRAM_BUCKETS - 1); i++) { + + if (i == 0) { + logMessage.append("\n\tless than " + + this.perfMetricsHistBreakpoints[i + 1] + + " ms: \t" + this.perfMetricsHistCounts[i]); + } else { + logMessage.append("\n\tbetween " + + this.perfMetricsHistBreakpoints[i] + " and " + + this.perfMetricsHistBreakpoints[i + 1] + + " ms: \t" + this.perfMetricsHistCounts[i]); + } + + logMessage.append("\t"); + + int numPointsToGraph = (int) (maxNumPoints * ((double) this.perfMetricsHistCounts[i] / (double) highestCount)); + + for (int j = 0; j < numPointsToGraph; j++) { + logMessage.append("*"); + } + + if (this.longestQueryTimeMs < this.perfMetricsHistCounts[i + 1]) { + break; + } + } + + if (this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2] < this.longestQueryTimeMs) { + logMessage.append("\n\tbetween "); + logMessage + .append(this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2]); + logMessage.append(" and "); + logMessage + .append(this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 1]); + logMessage.append(" ms: \t"); + logMessage + .append(this.perfMetricsHistCounts[HISTOGRAM_BUCKETS - 1]); + } + } + + if (this.numTablesMetricsHistBreakpoints != null) { + logMessage.append("\n\n\tTable Join Histogram:\n"); + int maxNumPoints = 20; + int highestCount = Integer.MIN_VALUE; + + for (int i = 0; i < (HISTOGRAM_BUCKETS); i++) { + if (this.numTablesMetricsHistCounts[i] > highestCount) { + highestCount = this.numTablesMetricsHistCounts[i]; + } + } + + if (highestCount == 0) { + highestCount = 1; // avoid DIV/0 + } + + for (int i = 0; i < (HISTOGRAM_BUCKETS - 1); i++) { + + if (i == 0) { + logMessage.append("\n\t" + + this.numTablesMetricsHistBreakpoints[i + 1] + + " tables or less: \t\t" + + this.numTablesMetricsHistCounts[i]); + } else { + logMessage.append("\n\tbetween " + + this.numTablesMetricsHistBreakpoints[i] + + " and " + + this.numTablesMetricsHistBreakpoints[i + 1] + + " tables: \t" + + this.numTablesMetricsHistCounts[i]); + } + + logMessage.append("\t"); + + int numPointsToGraph = (int) (maxNumPoints * ((double) this.numTablesMetricsHistCounts[i] / (double) highestCount)); + + for (int j = 0; j < numPointsToGraph; j++) { + logMessage.append("*"); + } + + if (this.maximumNumberTablesAccessed < this.numTablesMetricsHistBreakpoints[i + 1]) { + break; + } + } + + if (this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2] < this.maximumNumberTablesAccessed) { + logMessage.append("\n\tbetween "); + logMessage + .append(this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2]); + logMessage.append(" and "); + logMessage + .append(this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 1]); + logMessage.append(" tables: "); + logMessage + .append(this.numTablesMetricsHistCounts[HISTOGRAM_BUCKETS - 1]); + } + } + + this.log.logInfo(logMessage); + + this.metricsLastReportedMs = System.currentTimeMillis(); + } + } + + /** + * Reports currently collected metrics if this feature is enabled and the + * timeout has passed. + */ + protected void reportMetricsIfNeeded() { + if (getGatherPerformanceMetrics()) { + if ((System.currentTimeMillis() - this.metricsLastReportedMs) > getReportMetricsIntervalMillis()) { + reportMetrics(); + } + } + } + + public void reportNumberOfTablesAccessed(int numTablesAccessed) { + if (numTablesAccessed < this.minimumNumberTablesAccessed) { + this.minimumNumberTablesAccessed = numTablesAccessed; + } + + if (numTablesAccessed > this.maximumNumberTablesAccessed) { + this.maximumNumberTablesAccessed = numTablesAccessed; + + repartitionTablesAccessedHistogram(); + } + + addToTablesAccessedHistogram(numTablesAccessed, 1); + } + + /** + * Resets the server-side state of this connection. Doesn't work for MySQL + * versions older than 4.0.6 or if isParanoid() is set (it will become a + * no-op in these cases). Usually only used from connection pooling code. + * + * @throws SQLException + * if the operation fails while resetting server state. + */ + public void resetServerState() throws SQLException { + if (!getParanoid() + && ((this.io != null) && versionMeetsMinimum(4, 0, 6))) { + changeUser(this.user, this.password); + } + } + + /** + * The method rollback() drops all changes made since the previous + * commit/rollback and releases any database locks currently held by the + * Connection. + * + * @exception SQLException + * if a database access error occurs + * @see commit + */ + public void rollback() throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + try { + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + if (!((ConnectionLifecycleInterceptor)each).rollback()) { + this.stopIterating = true; + } + } + }; + + iter.doForAll(); + + if (!iter.fullIteration()) { + return; + } + } + // no-op if _relaxAutoCommit == true + if (this.autoCommit && !getRelaxAutoCommit()) { + throw SQLError.createSQLException( + "Can't call rollback when autocommit=true", + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor()); + } else if (this.transactionsSupported) { + try { + rollbackNoChecks(); + } catch (SQLException sqlEx) { + // We ignore non-transactional tables if told to do so + if (getIgnoreNonTxTables() + && (sqlEx.getErrorCode() == SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) { + return; + } + throw sqlEx; + + } + } + } catch (SQLException sqlException) { + if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE + .equals(sqlException.getSQLState())) { + throw SQLError.createSQLException( + "Communications link failure during rollback(). Transaction resolution unknown.", + SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, getExceptionInterceptor()); + } + + throw sqlException; + } finally { + this.needsPing = this.getReconnectAtTxEnd(); + } + } + } + + /** + * @see Connection#rollback(Savepoint) + */ + public void rollback(final Savepoint savepoint) throws SQLException { + + synchronized (getConnectionMutex()) { + if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) { + checkClosed(); + + try { + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + if (!((ConnectionLifecycleInterceptor)each).rollback(savepoint)) { + this.stopIterating = true; + } + } + }; + + iter.doForAll(); + + if (!iter.fullIteration()) { + return; + } + } + + StringBuffer rollbackQuery = new StringBuffer( + "ROLLBACK TO SAVEPOINT "); + rollbackQuery.append('`'); + rollbackQuery.append(savepoint.getSavepointName()); + rollbackQuery.append('`'); + + java.sql.Statement stmt = null; + + try { + stmt = getMetadataSafeStatement(); + + stmt.executeUpdate(rollbackQuery.toString()); + } catch (SQLException sqlEx) { + int errno = sqlEx.getErrorCode(); + + if (errno == 1181) { + String msg = sqlEx.getMessage(); + + if (msg != null) { + int indexOfError153 = msg.indexOf("153"); + + if (indexOfError153 != -1) { + throw SQLError.createSQLException("Savepoint '" + + savepoint.getSavepointName() + + "' does not exist", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + errno, getExceptionInterceptor()); + } + } + } + + // We ignore non-transactional tables if told to do so + if (getIgnoreNonTxTables() + && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) { + throw sqlEx; + } + + if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE + .equals(sqlEx.getSQLState())) { + throw SQLError.createSQLException( + "Communications link failure during rollback(). Transaction resolution unknown.", + SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, getExceptionInterceptor()); + } + + throw sqlEx; + } finally { + closeStatement(stmt); + } + } finally { + this.needsPing = this.getReconnectAtTxEnd(); + } + } else { + throw SQLError.notImplemented(); + } + } + } + + private void rollbackNoChecks() throws SQLException { + if (getUseLocalTransactionState() && versionMeetsMinimum(5, 0, 0)) { + if (!this.io.inTransactionOnServer()) { + return; // effectively a no-op + } + } + + execSQL(null, "rollback", -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + } + + /** + * @see java.sql.Connection#prepareStatement(String) + */ + public java.sql.PreparedStatement serverPrepareStatement(String sql) + throws SQLException { + + String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; + + return ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, this.getCatalog(), + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY); + } + + /** + * @see java.sql.Connection#prepareStatement(String, int) + */ + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; + + PreparedStatement pStmt = ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, this.getCatalog(), + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY); + + pStmt.setRetrieveGeneratedKeys( + autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS); + + return pStmt; + } + + /** + * @see java.sql.Connection#prepareStatement(String, int, int) + */ + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql; + + return ServerPreparedStatement.getInstance(getLoadBalanceSafeProxy(), nativeSql, this.getCatalog(), + resultSetType, + resultSetConcurrency); + } + + /** + * @see java.sql.Connection#prepareStatement(String, int, int, int) + */ + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + if (getPedantic()) { + if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) { + throw SQLError.createSQLException( + "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return serverPrepareStatement(sql, resultSetType, resultSetConcurrency); + } + + /** + * @see java.sql.Connection#prepareStatement(String, int[]) + */ + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + + PreparedStatement pStmt = (PreparedStatement) serverPrepareStatement(sql); + + pStmt + .setRetrieveGeneratedKeys((autoGenKeyIndexes != null) + && (autoGenKeyIndexes.length > 0)); + + return pStmt; + } + + /** + * @see java.sql.Connection#prepareStatement(String, String[]) + */ + public java.sql.PreparedStatement serverPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + PreparedStatement pStmt = (PreparedStatement) serverPrepareStatement(sql); + + pStmt + .setRetrieveGeneratedKeys((autoGenKeyColNames != null) + && (autoGenKeyColNames.length > 0)); + + return pStmt; + } + + public boolean serverSupportsConvertFn() throws SQLException { + return versionMeetsMinimum(4, 0, 2); + } + + /** + * If a connection is in auto-commit mode, than all its SQL statements will + * be executed and committed as individual transactions. Otherwise, its SQL + * statements are grouped into transactions that are terminated by either + * commit() or rollback(). By default, new connections are in auto- commit + * mode. The commit occurs when the statement completes or the next execute + * occurs, whichever comes first. In the case of statements returning a + * ResultSet, the statement completes when the last row of the ResultSet has + * been retrieved or the ResultSet has been closed. In advanced cases, a + * single statement may return multiple results as well as output parameter + * values. Here the commit occurs when all results and output param values + * have been retrieved. + *

+ * Note: MySQL does not support transactions, so this method is a + * no-op. + *

+ * + * @param autoCommitFlag - + * true enables auto-commit; false disables it + * @exception SQLException + * if a database access error occurs + */ + public void setAutoCommit(final boolean autoCommitFlag) throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + if (!((ConnectionLifecycleInterceptor)each).setAutoCommit(autoCommitFlag)) { + this.stopIterating = true; + } + } + }; + + iter.doForAll(); + + if (!iter.fullIteration()) { + return; + } + } + + if (getAutoReconnectForPools()) { + setHighAvailability(true); + } + + try { + if (this.transactionsSupported) { + + boolean needsSetOnServer = true; + + if (this.getUseLocalSessionState() + && this.autoCommit == autoCommitFlag) { + needsSetOnServer = false; + } else if (!this.getHighAvailability()) { + needsSetOnServer = this.getIO() + .isSetNeededForAutoCommitMode(autoCommitFlag); + } + + // this internal value must be set first as failover depends on + // it + // being set to true to fail over (which is done by most + // app servers and connection pools at the end of + // a transaction), and the driver issues an implicit set + // based on this value when it (re)-connects to a server + // so the value holds across connections + this.autoCommit = autoCommitFlag; + + if (needsSetOnServer) { + execSQL(null, autoCommitFlag ? "SET autocommit=1" + : "SET autocommit=0", -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + } + + } else { + if ((autoCommitFlag == false) && !getRelaxAutoCommit()) { + throw SQLError.createSQLException("MySQL Versions Older than 3.23.15 " + + "do not support transactions", + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor()); + } + + this.autoCommit = autoCommitFlag; + } + } finally { + if (this.getAutoReconnectForPools()) { + setHighAvailability(false); + } + } + + return; + } + } + + /** + * A sub-space of this Connection's database may be selected by setting a + * catalog name. If the driver does not support catalogs, it will silently + * ignore this request + *

+ * Note: MySQL's notion of catalogs are individual databases. + *

+ * + * @param catalog + * the database for this connection to use + * @throws SQLException + * if a database access error occurs + */ + public void setCatalog(final String catalog) throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + if (catalog == null) { + throw SQLError.createSQLException("Catalog can not be null", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + if (!((ConnectionLifecycleInterceptor)each).setCatalog(catalog)) { + this.stopIterating = true; + } + } + }; + + iter.doForAll(); + + if (!iter.fullIteration()) { + return; + } + } + + if (getUseLocalSessionState()) { + if (this.lowerCaseTableNames) { + if (this.database.equalsIgnoreCase(catalog)) { + return; + } + } else { + if (this.database.equals(catalog)) { + return; + } + } + } + + String quotedId = this.dbmd.getIdentifierQuoteString(); + + if ((quotedId == null) || quotedId.equals(" ")) { + quotedId = ""; + } + + StringBuffer query = new StringBuffer("USE "); + query.append(quotedId); + query.append(catalog); + query.append(quotedId); + + execSQL(null, query.toString(), -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + + this.database = catalog; + } + } + + /** + * @param failedOver + * The failedOver to set. + */ + public void setFailedOver(boolean flag) { + synchronized (getConnectionMutex()) { + // handled higher up + } + } + + /** + * @see Connection#setHoldability(int) + */ + public void setHoldability(int arg0) throws SQLException { + // do nothing + } + + public void setInGlobalTx(boolean flag) { + this.isInGlobalTx = flag; + } + + // exposed for testing + /** + * @param preferSlaveDuringFailover + * The preferSlaveDuringFailover to set. + */ + public void setPreferSlaveDuringFailover(boolean flag) { + // no-op, handled further up in the wrapper + } + + public void setReadInfoMsgEnabled(boolean flag) { + this.readInfoMsg = flag; + } + + /** + * You can put a connection in read-only mode as a hint to enable database + * optimizations Note: setReadOnly cannot be called while in the + * middle of a transaction + * + * @param readOnlyFlag - + * true enables read-only mode; false disables it + * @exception SQLException + * if a database access error occurs + */ + public void setReadOnly(boolean readOnlyFlag) throws SQLException { + checkClosed(); + + setReadOnlyInternal(readOnlyFlag); + } + + public void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException { + // note this this is safe even inside a transaction + if (versionMeetsMinimum(5, 6, 5)) { + if (!getUseLocalSessionState() || (readOnlyFlag != this.readOnly)) { + execSQL(null, "set session transaction " + (readOnlyFlag ? "read only" : "read write"), -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, + false); + } + } + + this.readOnly = readOnlyFlag; + } + + /** + * @see Connection#setSavepoint() + */ + public java.sql.Savepoint setSavepoint() throws SQLException { + MysqlSavepoint savepoint = new MysqlSavepoint(getExceptionInterceptor()); + + setSavepoint(savepoint); + + return savepoint; + } + + private void setSavepoint(MysqlSavepoint savepoint) throws SQLException { + + synchronized (getConnectionMutex()) { + if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) { + checkClosed(); + + StringBuffer savePointQuery = new StringBuffer("SAVEPOINT "); + savePointQuery.append('`'); + savePointQuery.append(savepoint.getSavepointName()); + savePointQuery.append('`'); + + java.sql.Statement stmt = null; + + try { + stmt = getMetadataSafeStatement(); + + stmt.executeUpdate(savePointQuery.toString()); + } finally { + closeStatement(stmt); + } + } else { + throw SQLError.notImplemented(); + } + } + } + + /** + * @see Connection#setSavepoint(String) + */ + public java.sql.Savepoint setSavepoint(String name) throws SQLException { + synchronized (getConnectionMutex()) { + MysqlSavepoint savepoint = new MysqlSavepoint(name, getExceptionInterceptor()); + + setSavepoint(savepoint); + + return savepoint; + } + } + + /** + * + */ + private void setSessionVariables() throws SQLException { + if (this.versionMeetsMinimum(4, 0, 0) && getSessionVariables() != null) { + List variablesToSet = StringUtils.split(getSessionVariables(), ",", "\"'", "\"'", + false); + + int numVariablesToSet = variablesToSet.size(); + + java.sql.Statement stmt = null; + + try { + stmt = getMetadataSafeStatement(); + + for (int i = 0; i < numVariablesToSet; i++) { + String variableValuePair = variablesToSet.get(i); + + if (variableValuePair.startsWith("@")) { + stmt.executeUpdate("SET " + variableValuePair); + } else { + stmt.executeUpdate("SET SESSION " + variableValuePair); + } + } + } finally { + if (stmt != null) { + stmt.close(); + } + } + } + + } + + /** + * DOCUMENT ME! + * + * @param level + * DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + public void setTransactionIsolation(int level) throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + if (this.hasIsolationLevels) { + String sql = null; + + boolean shouldSendSet = false; + + if (getAlwaysSendSetIsolation()) { + shouldSendSet = true; + } else { + if (level != this.isolationLevel) { + shouldSendSet = true; + } + } + + if (getUseLocalSessionState()) { + shouldSendSet = this.isolationLevel != level; + } + + if (shouldSendSet) { + switch (level) { + case java.sql.Connection.TRANSACTION_NONE: + throw SQLError.createSQLException("Transaction isolation level " + + "NONE not supported by MySQL", getExceptionInterceptor()); + + case java.sql.Connection.TRANSACTION_READ_COMMITTED: + sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"; + + break; + + case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED: + sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"; + + break; + + case java.sql.Connection.TRANSACTION_REPEATABLE_READ: + sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"; + + break; + + case java.sql.Connection.TRANSACTION_SERIALIZABLE: + sql = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE"; + + break; + + default: + throw SQLError.createSQLException("Unsupported transaction " + + "isolation level '" + level + "'", + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); + } + + execSQL(null, sql, -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY,false, + this.database, null, false); + + this.isolationLevel = level; + } + } else { + throw SQLError.createSQLException("Transaction Isolation Levels are " + + "not supported on MySQL versions older than 3.23.36.", + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); + } + } + } + + /** + * JDBC 2.0 Install a type-map object as the default type-map for this + * connection + * + * @param map + * the type mapping + * @throws SQLException + * if a database error occurs. + */ + public void setTypeMap(java.util.Map> map) throws SQLException { + synchronized (getConnectionMutex()) { + this.typeMap = map; + } + } + + private void setupServerForTruncationChecks() throws SQLException { + if (getJdbcCompliantTruncation()) { + if (versionMeetsMinimum(5, 0, 2)) { + String currentSqlMode = + this.serverVariables.get("sql_mode"); + + boolean strictTransTablesIsSet = StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") != -1; + + if (currentSqlMode == null || + currentSqlMode.length() == 0 || !strictTransTablesIsSet) { + StringBuffer commandBuf = new StringBuffer("SET sql_mode='"); + + if (currentSqlMode != null && currentSqlMode.length() > 0) { + commandBuf.append(currentSqlMode); + commandBuf.append(","); + } + + commandBuf.append("STRICT_TRANS_TABLES'"); + + execSQL(null, commandBuf.toString(), -1, null, + DEFAULT_RESULT_SET_TYPE, + DEFAULT_RESULT_SET_CONCURRENCY, false, + this.database, null, false); + + setJdbcCompliantTruncation(false); // server's handling this for us now + } else if (strictTransTablesIsSet) { + // We didn't set it, but someone did, so we piggy back on it + setJdbcCompliantTruncation(false); // server's handling this for us now + } + + } + } + } + + /** + * Used by MiniAdmin to shutdown a MySQL server + * + * @throws SQLException + * if the command can not be issued. + */ + public void shutdownServer() throws SQLException { + try { + this.io.sendCommand(MysqlDefs.SHUTDOWN, null, null, false, null, 0); + } catch (Exception ex) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Connection.UnhandledExceptionDuringShutdown"), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + + sqlEx.initCause(ex); + + throw sqlEx; + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean supportsIsolationLevel() { + return this.hasIsolationLevels; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean supportsQuotedIdentifiers() { + return this.hasQuotedIdentifiers; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean supportsTransactions() { + return this.transactionsSupported; + } + + /** + * Remove the given statement from the list of open statements + * + * @param stmt + * the Statement instance to remove + */ + public void unregisterStatement(Statement stmt) { + if (this.openStatements != null) { + synchronized (this.openStatements) { + this.openStatements.remove(stmt); + } + } + } + + public boolean useAnsiQuotedIdentifiers() { + synchronized (getConnectionMutex()) { + return this.useAnsiQuotes; + } + } + + public boolean versionMeetsMinimum(int major, int minor, int subminor) + throws SQLException { + checkClosed(); + + return this.io.versionMeetsMinimum(major, minor, subminor); + } + + /** + * Returns cached metadata (or null if not cached) for the given query, + * which must match _exactly_. + * + * This method is synchronized by the caller on getMutex(), so if + * calling this method from internal code in the driver, make sure it's + * synchronized on the mutex that guards communication with the server. + * + * @param sql + * the query that is the key to the cache + * + * @return metadata cached for the given SQL, or none if it doesn't + * exist. + */ + public CachedResultSetMetaData getCachedMetaData(String sql) { + if (this.resultSetMetadataCache != null) { + synchronized (this.resultSetMetadataCache) { + return (CachedResultSetMetaData) this.resultSetMetadataCache + .get(sql); + } + } + + return null; // no cache exists + } + + /** + * Caches CachedResultSetMetaData that has been placed in the cache using + * the given SQL as a key. + * + * This method is synchronized by the caller on getMutex(), so if + * calling this method from internal code in the driver, make sure it's + * synchronized on the mutex that guards communication with the server. + * + * @param sql the query that the metadata pertains too. + * @param cachedMetaData metadata (if it exists) to populate the cache. + * @param resultSet the result set to retreive metadata from, or apply to. + * + * @throws SQLException + */ + public void initializeResultsMetadataFromCache(String sql, + CachedResultSetMetaData cachedMetaData, ResultSetInternalMethods resultSet) + throws SQLException { + + if (cachedMetaData == null) { + + // read from results + cachedMetaData = new CachedResultSetMetaData(); + + // assume that users will use named-based + // lookups + resultSet.buildIndexMapping(); + resultSet.initializeWithMetadata(); + + if (resultSet instanceof UpdatableResultSet) { + ((UpdatableResultSet)resultSet).checkUpdatability(); + } + + resultSet.populateCachedMetaData(cachedMetaData); + + this.resultSetMetadataCache.put(sql, cachedMetaData); + } else { + resultSet.initializeFromCachedMetaData(cachedMetaData); + resultSet.initializeWithMetadata(); + + if (resultSet instanceof UpdatableResultSet) { + ((UpdatableResultSet)resultSet).checkUpdatability(); + } + } + } + + /** + * Returns the comment that will be prepended to all statements + * sent to the server. + * + * @return the comment that will be prepended to all statements + * sent to the server. + */ + public String getStatementComment() { + return this.statementComment; + } + + /** + * Sets the comment that will be prepended to all statements + * sent to the server. Do not use slash-star or star-slash tokens + * in the comment as these will be added by the driver itself. + * + * @param comment the comment that will be prepended to all statements + * sent to the server. + */ + public void setStatementComment(String comment) { + this.statementComment = comment; + } + + public void reportQueryTime(long millisOrNanos) { + synchronized (getConnectionMutex()) { + this.queryTimeCount++; + this.queryTimeSum += millisOrNanos; + this.queryTimeSumSquares += (millisOrNanos * millisOrNanos); + this.queryTimeMean = ((this.queryTimeMean * (this.queryTimeCount - 1)) + millisOrNanos) + / this.queryTimeCount; + } + } + + public boolean isAbonormallyLongQuery(long millisOrNanos) { + synchronized (getConnectionMutex()) { + if (this.queryTimeCount < 15) { + return false; // need a minimum amount for this to make sense + } + + double stddev = Math.sqrt((this.queryTimeSumSquares - ((this.queryTimeSum*this.queryTimeSum) / this.queryTimeCount)) / (this.queryTimeCount - 1)); + + return millisOrNanos > (this.queryTimeMean + 5 * stddev); + } + } + + public void initializeExtension(Extension ex) throws SQLException { + ex.init(this, this.props); + } + + public void transactionBegun() throws SQLException { + synchronized (getConnectionMutex()) { + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + ((ConnectionLifecycleInterceptor)each).transactionBegun(); + } + }; + + iter.doForAll(); + } + } + } + + public void transactionCompleted() throws SQLException { + synchronized (getConnectionMutex()) { + if (this.connectionLifecycleInterceptors != null) { + IterateBlock iter = new IterateBlock(this.connectionLifecycleInterceptors.iterator()) { + + void forEach(Extension each) throws SQLException { + ((ConnectionLifecycleInterceptor)each).transactionCompleted(); + } + }; + + iter.doForAll(); + } + } + } + + public boolean storesLowerCaseTableName() { + return storesLowerCaseTableName; + } + + private ExceptionInterceptor exceptionInterceptor; + + public ExceptionInterceptor getExceptionInterceptor() { + return this.exceptionInterceptor; + } + + public boolean getRequiresEscapingEncoder() { + return requiresEscapingEncoder; + } + + public boolean isServerLocal() throws SQLException { + synchronized (getConnectionMutex()) { + SocketFactory factory = getIO().socketFactory; + + if (factory instanceof SocketMetadata) { + return ((SocketMetadata)factory).isLocallyConnected(this); + } + getLog().logWarn(Messages.getString("Connection.NoMetadataOnSocketFactory")); + return false; + } + } + + /** + * Returns the sql select limit max-rows for this session. + */ + public int getSessionMaxRows() { + synchronized (getConnectionMutex()) { + return this.sessionMaxRows; + } + } + + /** + * Sets the sql select limit max-rows for this session if different from current. + * + * @param max + * the new max-rows value to set. + * @throws SQLException + * if a database error occurs issuing the statement that sets the limit. + */ + public void setSessionMaxRows(int max) throws SQLException { + synchronized (getConnectionMutex()) { + if (this.sessionMaxRows != max) { + this.sessionMaxRows = max; + execSQL(null, "SET SQL_SELECT_LIMIT=" + (this.sessionMaxRows == -1 ? "DEFAULT" : this.sessionMaxRows), -1, null, + DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY, false, this.database, null, false); + } + } + } + + // JDBC-4.1 + // until we flip catalog/schema, this is a no-op + public void setSchema(String schema) throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + } + } + + // JDBC-4.1 + public String getSchema() throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + + return null; + } + } + + /** + * Terminates an open connection. Calling abort results in: + *
    + *
  • The connection marked as closed + *
  • Closes any physical connection to the database + *
  • Releases resources used by the connection + *
  • Insures that any thread that is currently accessing the connection + * will either progress to completion or throw an SQLException. + *
+ *

+ * Calling abort marks the connection closed and releases any + * resources. Calling abort on a closed connection is a + * no-op. + *

+ * It is possible that the aborting and releasing of the resources that are + * held by the connection can take an extended period of time. When the + * abort method returns, the connection will have been marked as + * closed and the Executor that was passed as a parameter to abort + * may still be executing tasks to release resources. + *

+ * This method checks to see that there is an SQLPermission + * object before allowing the method to proceed. If a + * SecurityManager exists and its + * checkPermission method denies calling abort, + * this method throws a + * java.lang.SecurityException. + * @param executor The Executor implementation which will + * be used by abort. + * @throws java.sql.SQLException if a database access error occurs or + * the {@code executor} is {@code null}, + * @throws java.lang.SecurityException if a security manager exists and its + * checkPermission method denies calling abort + * @see SecurityManager#checkPermission + * @see Executor + * @since 1.7 + */ + public void abort(Executor executor) throws SQLException { + SecurityManager sec = System.getSecurityManager(); + + if (sec != null) { + sec.checkPermission(ABORT_PERM); + } + + if (executor == null) { + throw SQLError.createSQLException("Executor can not be null", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + executor.execute(new Runnable() { + + public void run() { + try { + abortInternal(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + }); + } + + // JDBC-4.1 + public void setNetworkTimeout(Executor executor, final int milliseconds) throws SQLException { + synchronized (getConnectionMutex()) { + SecurityManager sec = System.getSecurityManager(); + + if (sec != null) { + sec.checkPermission(SET_NETWORK_TIMEOUT_PERM); + } + + if (executor == null) { + throw SQLError.createSQLException("Executor can not be null", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + checkClosed(); + final MysqlIO mysqlIo = this.io; + + executor.execute(new Runnable() { + + public void run() { + try { + setSocketTimeout(milliseconds); // for re-connects + mysqlIo.setSocketTimeout(milliseconds); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }}); + } + } + + // JDBC-4.1 + public int getNetworkTimeout() throws SQLException { + synchronized (getConnectionMutex()) { + checkClosed(); + return getSocketTimeout(); + } + } + + public ProfilerEventHandler getProfilerEventHandlerInstance() { + return this.eventSink; + } + + public void setProfilerEventHandlerInstance(ProfilerEventHandler h) { + this.eventSink = h; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionLifecycleInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionLifecycleInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionLifecycleInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,127 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.sql.Savepoint; + +/** + * Implementors of this interface can be installed via the + * "connectionLifecycleInterceptors" configuration property and receive + * events and alter behavior of "lifecycle" methods on our connection + * implementation. + * + * The driver will create one instance of a given interceptor per-connection. + */ +public interface ConnectionLifecycleInterceptor extends Extension { + /** + * Called when an application calls Connection.close(), before the driver + * processes its own internal logic for close. + * + * @throws SQLException + */ + public abstract void close() throws SQLException; + + /** + * Called when an application calls Connection.commit(), before the + * driver processes its own internal logic for commit(). + * + * Interceptors should return "true" if the driver should perform + * its own internal logic for commit(), or "false" if not. + * + * @return "true" if the driver should perform + * its own internal logic for commit(), or "false" if not. + * + * @throws SQLException if an error occurs + */ + public abstract boolean commit() throws SQLException; + + /** + * Called when an application calls Connection.rollback(), before the + * driver processes its own internal logic for rollback(). + * + * Interceptors should return "true" if the driver should perform + * its own internal logic for rollback(), or "false" if not. + * + * @return "true" if the driver should perform + * its own internal logic for rollback(), or "false" if not. + * + * @throws SQLException if an error occurs + */ + public abstract boolean rollback() throws SQLException; + + /** + * Called when an application calls Connection.rollback(), before the + * driver processes its own internal logic for rollback(). + * + * Interceptors should return "true" if the driver should perform + * its own internal logic for rollback(), or "false" if not. + * + * @return "true" if the driver should perform + * its own internal logic for rollback(), or "false" if not. + * + * @throws SQLException if an error occurs + */ + public abstract boolean rollback(Savepoint s) throws SQLException; + + /** + * Called when an application calls Connection.setAutoCommit(), before the + * driver processes its own internal logic for setAutoCommit(). + * + * Interceptors should return "true" if the driver should perform + * its own internal logic for setAutoCommit(), or "false" if not. + * + * @return "true" if the driver should perform + * its own internal logic for setAutoCommit(), or "false" if not. + * + * @throws SQLException if an error occurs + */ + public abstract boolean setAutoCommit(boolean flag) throws SQLException; + + /** + * Called when an application calls Connection.setCatalog(), before the + * driver processes its own internal logic for setCatalog(). + * + * Interceptors should return "true" if the driver should perform + * its own internal logic for setCatalog(), or "false" if not. + * + * @return "true" if the driver should perform + * its own internal logic for setCatalog(), or "false" if not. + * + * @throws SQLException if an error occurs + */ + public abstract boolean setCatalog(String catalog) throws SQLException; + + /** + * Called when the driver has been told by the server that a transaction + * is now in progress (when one has not been currently in progress). + */ + public abstract boolean transactionBegun() throws SQLException; + + /** + * Called when the driver has been told by the server that a transaction + * has completed, and no transaction is currently in progress. + */ + public abstract boolean transactionCompleted() throws SQLException; +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionProperties.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionProperties.java (.../ConnectionProperties.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionProperties.java (.../ConnectionProperties.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,4184 +1,1750 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import com.mysql.jdbc.log.Jdk14Logger; -import com.mysql.jdbc.log.Log; -import com.mysql.jdbc.log.StandardLogger; - -import java.io.Serializable; -import java.io.UnsupportedEncodingException; - -import java.sql.DriverPropertyInfo; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.TreeMap; +public interface ConnectionProperties { -import javax.naming.RefAddr; -import javax.naming.Reference; -import javax.naming.StringRefAddr; - -/** - * Represents configurable properties for Connections and DataSources. Can also - * expose properties as JDBC DriverPropertyInfo if required as well. - * - * @author Mark Matthews - * @version $Id: ConnectionProperties.java,v 1.1.2.2 2005/05/17 14:58:56 - * mmatthews Exp $ - */ -public class ConnectionProperties implements Serializable { - - private static final long serialVersionUID = 4257801713007640580L; - - class BooleanConnectionProperty extends ConnectionProperty implements Serializable { - - private static final long serialVersionUID = 2540132501709159404L; - - /** - * DOCUMENT ME! - * - * @param propertyNameToSet - * @param defaultValueToSet - * @param descriptionToSet - * DOCUMENT ME! - * @param sinceVersionToSet - * DOCUMENT ME! - */ - BooleanConnectionProperty(String propertyNameToSet, - boolean defaultValueToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - super(propertyNameToSet, new Boolean(defaultValueToSet), null, 0, - 0, descriptionToSet, sinceVersionToSet, category, - orderInCategory); - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getAllowableValues() - */ - String[] getAllowableValues() { - return new String[] { "true", "false", "yes", "no" }; - } - - boolean getValueAsBoolean() { - return ((Boolean) this.valueAsObject).booleanValue(); - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#hasValueConstraints() - */ - boolean hasValueConstraints() { - return true; - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#initializeFrom(java.util.Properties) - */ - void initializeFrom(String extractedValue) throws SQLException { - if (extractedValue != null) { - validateStringValues(extractedValue); - - this.valueAsObject = new Boolean(extractedValue - .equalsIgnoreCase("TRUE") - || extractedValue.equalsIgnoreCase("YES")); - } else { - this.valueAsObject = this.defaultValue; - } - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#isRangeBased() - */ - boolean isRangeBased() { - return false; - } - - void setValue(boolean valueFlag) { - this.valueAsObject = new Boolean(valueFlag); - } - } - - abstract class ConnectionProperty implements Serializable { - String[] allowableValues; - - String categoryName; - - Object defaultValue; - - int lowerBound; - - int order; - - String propertyName; - - String sinceVersion; - - int upperBound; - - Object valueAsObject; - - boolean required; - - String description; - - public ConnectionProperty() {} - - ConnectionProperty(String propertyNameToSet, Object defaultValueToSet, - String[] allowableValuesToSet, int lowerBoundToSet, - int upperBoundToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - - this.description = descriptionToSet; - this.propertyName = propertyNameToSet; - this.defaultValue = defaultValueToSet; - this.valueAsObject = defaultValueToSet; - this.allowableValues = allowableValuesToSet; - this.lowerBound = lowerBoundToSet; - this.upperBound = upperBoundToSet; - this.required = false; - this.sinceVersion = sinceVersionToSet; - this.categoryName = category; - this.order = orderInCategory; - } - - String[] getAllowableValues() { - return this.allowableValues; - } - - /** - * @return Returns the categoryName. - */ - String getCategoryName() { - return this.categoryName; - } - - Object getDefaultValue() { - return this.defaultValue; - } - - int getLowerBound() { - return this.lowerBound; - } - - /** - * @return Returns the order. - */ - int getOrder() { - return this.order; - } - - String getPropertyName() { - return this.propertyName; - } - - int getUpperBound() { - return this.upperBound; - } - - Object getValueAsObject() { - return this.valueAsObject; - } - - abstract boolean hasValueConstraints(); - - void initializeFrom(Properties extractFrom) throws SQLException { - String extractedValue = extractFrom.getProperty(getPropertyName()); - extractFrom.remove(getPropertyName()); - initializeFrom(extractedValue); - } - - void initializeFrom(Reference ref) throws SQLException { - RefAddr refAddr = ref.get(getPropertyName()); - - if (refAddr != null) { - String refContentAsString = (String) refAddr.getContent(); - - initializeFrom(refContentAsString); - } - } - - abstract void initializeFrom(String extractedValue) throws SQLException; - - abstract boolean isRangeBased(); - - /** - * @param categoryName - * The categoryName to set. - */ - void setCategoryName(String categoryName) { - this.categoryName = categoryName; - } - - /** - * @param order - * The order to set. - */ - void setOrder(int order) { - this.order = order; - } - - void setValueAsObject(Object obj) { - this.valueAsObject = obj; - } - - void storeTo(Reference ref) { - if (getValueAsObject() != null) { - ref.add(new StringRefAddr(getPropertyName(), getValueAsObject() - .toString())); - } - } - - DriverPropertyInfo getAsDriverPropertyInfo() { - DriverPropertyInfo dpi = new DriverPropertyInfo(this.propertyName, null); - dpi.choices = getAllowableValues(); - dpi.value = (this.valueAsObject != null) ? this.valueAsObject.toString() : null; - dpi.required = this.required; - dpi.description = this.description; - - return dpi; - } - - - void validateStringValues(String valueToValidate) throws SQLException { - String[] validateAgainst = getAllowableValues(); - - if (valueToValidate == null) { - return; - } - - if ((validateAgainst == null) || (validateAgainst.length == 0)) { - return; - } - - for (int i = 0; i < validateAgainst.length; i++) { - if ((validateAgainst[i] != null) - && validateAgainst[i].equalsIgnoreCase(valueToValidate)) { - return; - } - } - - StringBuffer errorMessageBuf = new StringBuffer(); - - errorMessageBuf.append("The connection property '"); - errorMessageBuf.append(getPropertyName()); - errorMessageBuf.append("' only accepts values of the form: "); - - if (validateAgainst.length != 0) { - errorMessageBuf.append("'"); - errorMessageBuf.append(validateAgainst[0]); - errorMessageBuf.append("'"); - - for (int i = 1; i < (validateAgainst.length - 1); i++) { - errorMessageBuf.append(", "); - errorMessageBuf.append("'"); - errorMessageBuf.append(validateAgainst[i]); - errorMessageBuf.append("'"); - } - - errorMessageBuf.append(" or '"); - errorMessageBuf - .append(validateAgainst[validateAgainst.length - 1]); - errorMessageBuf.append("'"); - } - - errorMessageBuf.append(". The value '"); - errorMessageBuf.append(valueToValidate); - errorMessageBuf.append("' is not in this set."); - - throw SQLError.createSQLException(errorMessageBuf.toString(), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } - - class IntegerConnectionProperty extends ConnectionProperty implements Serializable { - - private static final long serialVersionUID = -3004305481796850832L; - - public IntegerConnectionProperty(String propertyNameToSet, - Object defaultValueToSet, String[] allowableValuesToSet, - int lowerBoundToSet, int upperBoundToSet, - String descriptionToSet, String sinceVersionToSet, - String category, int orderInCategory) { - super(propertyNameToSet, defaultValueToSet, allowableValuesToSet, - lowerBoundToSet, upperBoundToSet, descriptionToSet, sinceVersionToSet, - category, orderInCategory); - } - - int multiplier = 1; - - IntegerConnectionProperty(String propertyNameToSet, - int defaultValueToSet, int lowerBoundToSet, - int upperBoundToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - super(propertyNameToSet, new Integer(defaultValueToSet), null, - lowerBoundToSet, upperBoundToSet, descriptionToSet, - sinceVersionToSet, category, orderInCategory); - } - - /** - * DOCUMENT ME! - * - * @param propertyNameToSet - * @param defaultValueToSet - * @param descriptionToSet - * @param sinceVersionToSet - * DOCUMENT ME! - */ - - IntegerConnectionProperty(String propertyNameToSet, - int defaultValueToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - this(propertyNameToSet, defaultValueToSet, 0, 0, descriptionToSet, - sinceVersionToSet, category, orderInCategory); - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getAllowableValues() - */ - String[] getAllowableValues() { - return null; - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getLowerBound() - */ - int getLowerBound() { - return this.lowerBound; - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getUpperBound() - */ - int getUpperBound() { - return this.upperBound; - } - - int getValueAsInt() { - return ((Integer) this.valueAsObject).intValue(); - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#hasValueConstraints() - */ - boolean hasValueConstraints() { - return false; - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#initializeFrom(java.lang.String) - */ - void initializeFrom(String extractedValue) throws SQLException { - if (extractedValue != null) { - try { - // Parse decimals, too - int intValue = Double.valueOf(extractedValue).intValue(); - - /* - * if (isRangeBased()) { if ((intValue < getLowerBound()) || - * (intValue > getUpperBound())) { throw new - * SQLException("The connection property '" + - * getPropertyName() + "' only accepts integer values in the - * range of " + getLowerBound() + " - " + getUpperBound() + ", - * the value '" + extractedValue + "' exceeds this range.", - * SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } - */ - this.valueAsObject = new Integer(intValue * multiplier); - } catch (NumberFormatException nfe) { - throw SQLError.createSQLException("The connection property '" - + getPropertyName() - + "' only accepts integer values. The value '" - + extractedValue - + "' can not be converted to an integer.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } else { - this.valueAsObject = this.defaultValue; - } - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#isRangeBased() - */ - boolean isRangeBased() { - return getUpperBound() != getLowerBound(); - } - - void setValue(int valueFlag) { - this.valueAsObject = new Integer(valueFlag); - } - } - - public class LongConnectionProperty extends IntegerConnectionProperty { - - private static final long serialVersionUID = 6068572984340480895L; - - LongConnectionProperty(String propertyNameToSet, - long defaultValueToSet, long lowerBoundToSet, - long upperBoundToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - super(propertyNameToSet, new Long(defaultValueToSet), null, - (int)lowerBoundToSet, (int)upperBoundToSet, descriptionToSet, - sinceVersionToSet, category, orderInCategory); - } - - - LongConnectionProperty(String propertyNameToSet, - long defaultValueToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - this(propertyNameToSet, - defaultValueToSet, 0, - 0, descriptionToSet, - sinceVersionToSet, category, orderInCategory); - } - - void setValue(long value) { - this.valueAsObject = new Long(value); - } - - long getValueAsLong() { - return ((Long) this.valueAsObject).longValue(); - } - - void initializeFrom(String extractedValue) throws SQLException { - if (extractedValue != null) { - try { - // Parse decimals, too - long longValue = Double.valueOf(extractedValue).longValue(); - - this.valueAsObject = new Long(longValue); - } catch (NumberFormatException nfe) { - throw SQLError.createSQLException("The connection property '" - + getPropertyName() - + "' only accepts long integer values. The value '" - + extractedValue - + "' can not be converted to a long integer.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } else { - this.valueAsObject = this.defaultValue; - } - } - } - - class MemorySizeConnectionProperty extends IntegerConnectionProperty implements Serializable { - - private static final long serialVersionUID = 7351065128998572656L; - - MemorySizeConnectionProperty(String propertyNameToSet, - int defaultValueToSet, int lowerBoundToSet, - int upperBoundToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - super(propertyNameToSet, defaultValueToSet, lowerBoundToSet, - upperBoundToSet, descriptionToSet, sinceVersionToSet, - category, orderInCategory); - // TODO Auto-generated constructor stub - } - - void initializeFrom(String extractedValue) throws SQLException { - if (extractedValue != null) { - if (extractedValue.endsWith("k") - || extractedValue.endsWith("K") - || extractedValue.endsWith("kb") - || extractedValue.endsWith("Kb") - || extractedValue.endsWith("kB")) { - multiplier = 1024; - int indexOfK = StringUtils.indexOfIgnoreCase( - extractedValue, "k"); - extractedValue = extractedValue.substring(0, indexOfK); - } else if (extractedValue.endsWith("m") - || extractedValue.endsWith("M") - || extractedValue.endsWith("G") - || extractedValue.endsWith("mb") - || extractedValue.endsWith("Mb") - || extractedValue.endsWith("mB")) { - multiplier = 1024 * 1024; - int indexOfM = StringUtils.indexOfIgnoreCase( - extractedValue, "m"); - extractedValue = extractedValue.substring(0, indexOfM); - } else if (extractedValue.endsWith("g") - || extractedValue.endsWith("G") - || extractedValue.endsWith("gb") - || extractedValue.endsWith("Gb") - || extractedValue.endsWith("gB")) { - multiplier = 1024 * 1024 * 1024; - int indexOfG = StringUtils.indexOfIgnoreCase( - extractedValue, "g"); - extractedValue = extractedValue.substring(0, indexOfG); - } - } - - super.initializeFrom(extractedValue); - } - - void setValue(String value) throws SQLException { - initializeFrom(value); - } - } - - class StringConnectionProperty extends ConnectionProperty implements Serializable { - - private static final long serialVersionUID = 5432127962785948272L; - - StringConnectionProperty(String propertyNameToSet, - String defaultValueToSet, String descriptionToSet, - String sinceVersionToSet, String category, int orderInCategory) { - this(propertyNameToSet, defaultValueToSet, null, descriptionToSet, - sinceVersionToSet, category, orderInCategory); - } - - /** - * DOCUMENT ME! - * - * @param propertyNameToSet - * @param defaultValueToSet - * @param allowableValuesToSet - * @param descriptionToSet - * @param sinceVersionToSet - * DOCUMENT ME! - */ - StringConnectionProperty(String propertyNameToSet, - String defaultValueToSet, String[] allowableValuesToSet, - String descriptionToSet, String sinceVersionToSet, - String category, int orderInCategory) { - super(propertyNameToSet, defaultValueToSet, allowableValuesToSet, - 0, 0, descriptionToSet, sinceVersionToSet, category, - orderInCategory); - } - - String getValueAsString() { - return (String) this.valueAsObject; - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#hasValueConstraints() - */ - boolean hasValueConstraints() { - return (this.allowableValues != null) - && (this.allowableValues.length > 0); - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#initializeFrom(java.util.Properties) - */ - void initializeFrom(String extractedValue) throws SQLException { - if (extractedValue != null) { - validateStringValues(extractedValue); - - this.valueAsObject = extractedValue; - } else { - this.valueAsObject = this.defaultValue; - } - } - - /** - * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#isRangeBased() - */ - boolean isRangeBased() { - return false; - } - - void setValue(String valueFlag) { - this.valueAsObject = valueFlag; - } - } - - private static final String CONNECTION_AND_AUTH_CATEGORY = "Connection/Authentication"; - - private static final String NETWORK_CATEGORY = "Networking"; - - private static final String DEBUGING_PROFILING_CATEGORY = "Debuging/Profiling"; - - private static final String HA_CATEGORY = "High Availability and Clustering"; - - private static final String MISC_CATEGORY = "Miscellaneous"; - - private static final String PERFORMANCE_CATEGORY = "Performance Extensions"; - - private static final String SECURITY_CATEGORY = "Security"; - - private static final String[] PROPERTY_CATEGORIES = new String[] { - CONNECTION_AND_AUTH_CATEGORY, NETWORK_CATEGORY, - HA_CATEGORY, SECURITY_CATEGORY, - PERFORMANCE_CATEGORY, DEBUGING_PROFILING_CATEGORY, MISC_CATEGORY }; - - private static final ArrayList PROPERTY_LIST = new ArrayList(); - - private static final String STANDARD_LOGGER_NAME = StandardLogger.class.getName(); - - protected static final String ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL = "convertToNull"; - - protected static final String ZERO_DATETIME_BEHAVIOR_EXCEPTION = "exception"; - - protected static final String ZERO_DATETIME_BEHAVIOR_ROUND = "round"; - - static { - try { - java.lang.reflect.Field[] declaredFields = ConnectionProperties.class - .getDeclaredFields(); - - for (int i = 0; i < declaredFields.length; i++) { - if (ConnectionProperties.ConnectionProperty.class - .isAssignableFrom(declaredFields[i].getType())) { - PROPERTY_LIST.add(declaredFields[i]); - } - } - } catch (Exception ex) { - throw new RuntimeException(ex.toString()); - } - } - /** - * Exposes all ConnectionPropertyInfo instances as DriverPropertyInfo - * - * @param info - * the properties to load into these ConnectionPropertyInfo - * instances - * @param slotsToReserve - * the number of DPI slots to reserve for 'standard' DPI - * properties (user, host, password, etc) - * @return a list of all ConnectionPropertyInfo instances, as - * DriverPropertyInfo - * @throws SQLException - * if an error occurs - */ - protected static DriverPropertyInfo[] exposeAsDriverPropertyInfo( - Properties info, int slotsToReserve) throws SQLException { - return (new ConnectionProperties() { - }).exposeAsDriverPropertyInfoInternal(info, slotsToReserve); - } - - private BooleanConnectionProperty allowLoadLocalInfile = new BooleanConnectionProperty( - "allowLoadLocalInfile", - true, - "Should the driver allow use of 'LOAD DATA LOCAL INFILE...' (defaults to 'true').", - "3.0.3", SECURITY_CATEGORY, Integer.MAX_VALUE); - - private BooleanConnectionProperty allowMultiQueries = new BooleanConnectionProperty( - "allowMultiQueries", - false, - "Allow the use of ';' to delimit multiple queries during one statement (true/false), defaults to 'false'", - "3.1.1", SECURITY_CATEGORY, 1); - - private BooleanConnectionProperty allowNanAndInf = new BooleanConnectionProperty( - "allowNanAndInf", - false, - "Should the driver allow NaN or +/- INF values in PreparedStatement.setDouble()?", - "3.1.5", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty allowUrlInLocalInfile = new BooleanConnectionProperty( - "allowUrlInLocalInfile", - false, - "Should the driver allow URLs in 'LOAD DATA LOCAL INFILE' statements?", - "3.1.4", SECURITY_CATEGORY, Integer.MAX_VALUE); - - private BooleanConnectionProperty alwaysSendSetIsolation = new BooleanConnectionProperty( - "alwaysSendSetIsolation", - true, - "Should the driver always communicate with the database when " - + " Connection.setTransactionIsolation() is called? " - + "If set to false, the driver will only communicate with the " - + "database when the requested transaction isolation is different " - + "than the whichever is newer, the last value that was set via " - + "Connection.setTransactionIsolation(), or the value that was read from " - + "the server when the connection was established.", - "3.1.7", PERFORMANCE_CATEGORY, Integer.MAX_VALUE); - - private BooleanConnectionProperty autoClosePStmtStreams = new BooleanConnectionProperty( - "autoClosePStmtStreams", - false, - "Should the driver automatically call .close() on streams/readers passed as " - + "arguments via set*() methods?", - "3.1.12", - MISC_CATEGORY, - Integer.MIN_VALUE); - - private BooleanConnectionProperty autoDeserialize = new BooleanConnectionProperty( - "autoDeserialize", - false, - "Should the driver automatically detect and de-serialize objects stored in BLOB fields?", - "3.1.5", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty autoGenerateTestcaseScript = new BooleanConnectionProperty( - "autoGenerateTestcaseScript", false, - "Should the driver dump the SQL it is executing, including server-side " - + "prepared statements to STDERR?", "3.1.9", - DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private boolean autoGenerateTestcaseScriptAsBoolean = false; - - private BooleanConnectionProperty autoReconnect = new BooleanConnectionProperty( - "autoReconnect", - false, - "Should the driver try to re-establish stale and/or dead connections? " - + " If enabled the driver will throw an exception for a queries issued on a stale or dead connection, " - + " which belong to the current transaction, but will attempt reconnect before the next query issued on the " - + "connection in a new transaction. The use of this feature " - + "is not recommended, because it has side effects related to session state and data consistency when applications don't" - + "handle SQLExceptions properly, and is only designed to be used " - + "when you are unable to configure your application to handle SQLExceptions resulting from dead and" - + "stale connections properly. Alternatively, investigate setting the MySQL server variable \"wait_timeout\"" - + "to some high value rather than the default of 8 hours.", - "1.1", HA_CATEGORY, 0); - - private BooleanConnectionProperty autoReconnectForPools = new BooleanConnectionProperty( - "autoReconnectForPools", - false, - "Use a reconnection strategy appropriate for connection pools (defaults to 'false')", - "3.1.3", HA_CATEGORY, 1); - - private boolean autoReconnectForPoolsAsBoolean = false; - - private MemorySizeConnectionProperty blobSendChunkSize = new MemorySizeConnectionProperty( - "blobSendChunkSize", - 1024 * 1024, - 1, - Integer.MAX_VALUE, - "Chunk to use when sending BLOB/CLOBs via ServerPreparedStatements", - "3.1.9", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty blobsAreStrings = new BooleanConnectionProperty( - "blobsAreStrings", false, - "Should the driver always treat BLOBs as Strings - specifically to work around dubious metadata " - + "returned by the server for GROUP BY clauses?", - "5.0.8", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty functionsNeverReturnBlobs = new BooleanConnectionProperty( - "functionsNeverReturnBlobs", false, - "Should the driver always treat data from functions returning BLOBs as Strings - specifically to work around dubious metadata " - + "returned by the server for GROUP BY clauses?", - "5.0.8", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty cacheCallableStatements = new BooleanConnectionProperty( - "cacheCallableStmts", false, - "Should the driver cache the parsing stage of CallableStatements", - "3.1.2", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty cachePreparedStatements = new BooleanConnectionProperty( - "cachePrepStmts", - false, - "Should the driver cache the parsing stage of PreparedStatements of client-side " - + "prepared statements, the \"check\" for suitability of server-side prepared " - + " and server-side prepared statements themselves?", - "3.0.10", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty cacheResultSetMetadata = new BooleanConnectionProperty( - "cacheResultSetMetadata", - false, - "Should the driver cache ResultSetMetaData for Statements and PreparedStatements? (Req. JDK-1.4+, true/false, default 'false')", - "3.1.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private boolean cacheResultSetMetaDataAsBoolean; - - private BooleanConnectionProperty cacheServerConfiguration = new BooleanConnectionProperty( - "cacheServerConfiguration", - false, - "Should the driver cache the results of " - + "'SHOW VARIABLES' and 'SHOW COLLATION' on a per-URL basis?", - "3.1.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty callableStatementCacheSize = new IntegerConnectionProperty( - "callableStmtCacheSize", - 100, - 0, - Integer.MAX_VALUE, - "If 'cacheCallableStmts' is enabled, how many callable statements should be cached?", - "3.1.2", PERFORMANCE_CATEGORY, 5); - - private BooleanConnectionProperty capitalizeTypeNames = new BooleanConnectionProperty( - "capitalizeTypeNames", - true, - "Capitalize type names in DatabaseMetaData? (usually only useful when using WebObjects, true/false, defaults to 'false')", - "2.0.7", MISC_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty characterEncoding = new StringConnectionProperty( - "characterEncoding", - null, - "If 'useUnicode' is set to true, what character encoding should the driver use when dealing with strings? (defaults is to 'autodetect')", - "1.1g", MISC_CATEGORY, 5); - - private String characterEncodingAsString = null; - - private StringConnectionProperty characterSetResults = new StringConnectionProperty( - "characterSetResults", null, - "Character set to tell the server to return results as.", "3.0.13", - MISC_CATEGORY, 6); - - private BooleanConnectionProperty clobberStreamingResults = new BooleanConnectionProperty( - "clobberStreamingResults", - false, - "This will cause a 'streaming' ResultSet to be automatically closed, " - + "and any outstanding data still streaming from the server to be discarded if another query is executed " - + "before all the data has been read from the server.", - "3.0.9", MISC_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty clobCharacterEncoding = new StringConnectionProperty( - "clobCharacterEncoding", - null, - "The character encoding to use for sending and retrieving TEXT, MEDIUMTEXT " + - "and LONGTEXT values instead of the configured connection characterEncoding", - "5.0.0", MISC_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty connectionCollation = new StringConnectionProperty( - "connectionCollation", - null, - "If set, tells the server to use this collation via 'set collation_connection'", - "3.0.13", MISC_CATEGORY, 7); - - private IntegerConnectionProperty connectTimeout = new IntegerConnectionProperty( - "connectTimeout", 0, 0, Integer.MAX_VALUE, - "Timeout for socket connect (in milliseconds), with 0 being no timeout. " - + "Only works on JDK-1.4 or newer. Defaults to '0'.", - "3.0.1", CONNECTION_AND_AUTH_CATEGORY, 9); - - private BooleanConnectionProperty continueBatchOnError = new BooleanConnectionProperty( - "continueBatchOnError", - true, - "Should the driver continue processing batch commands if " - + "one statement fails. The JDBC spec allows either way (defaults to 'true').", - "3.0.3", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty createDatabaseIfNotExist = new BooleanConnectionProperty( - "createDatabaseIfNotExist", - false, - "Creates the database given in the URL if it doesn't yet exist. Assumes " - + " the configured user has permissions to create databases.", - "3.1.9", MISC_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty defaultFetchSize = new IntegerConnectionProperty("defaultFetchSize", 0, "The driver will call setFetchSize(n) with this value on all newly-created Statements", "3.1.9", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty detectServerPreparedStmts = new BooleanConnectionProperty( - "useServerPrepStmts", - false, - "Use server-side prepared statements if the server supports them?", - "3.1.0", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty dontTrackOpenResources = new BooleanConnectionProperty( - "dontTrackOpenResources", - false, - "The JDBC specification requires the driver to automatically track and close resources, " - + "however if your application doesn't do a good job of " - + "explicitly calling close() on statements or result sets, " - + "this can cause memory leakage. Setting this property to true " - + "relaxes this constraint, and can be more memory efficient for " - + "some applications.", "3.1.7", PERFORMANCE_CATEGORY, - Integer.MIN_VALUE); - - private BooleanConnectionProperty dumpQueriesOnException = new BooleanConnectionProperty( - "dumpQueriesOnException", - false, - "Should the driver dump the contents of the query sent to the server in the message for SQLExceptions?", - "3.1.3", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty dynamicCalendars = new BooleanConnectionProperty( - "dynamicCalendars", - false, - "Should the driver retrieve the default" - + " calendar when required, or cache it per connection/session?", - "3.1.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty elideSetAutoCommits = new BooleanConnectionProperty( - "elideSetAutoCommits", - false, - "If using MySQL-4.1 or newer, should the driver only issue 'set autocommit=n' queries when the server's state doesn't match the requested state by Connection.setAutoCommit(boolean)?", - "3.1.3", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty emptyStringsConvertToZero = new BooleanConnectionProperty( - "emptyStringsConvertToZero", true, - "Should the driver allow conversions from empty string " - + "fields to numeric values of '0'?", "3.1.8", - MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty emulateLocators = new BooleanConnectionProperty( - "emulateLocators", false, "N/A", "3.1.0", MISC_CATEGORY, - Integer.MIN_VALUE); - - private BooleanConnectionProperty emulateUnsupportedPstmts = new BooleanConnectionProperty( - "emulateUnsupportedPstmts", - true, - "Should the driver detect prepared statements that are not supported by the server, and " - + "replace them with client-side emulated versions?", - "3.1.7", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty enablePacketDebug = new BooleanConnectionProperty( - "enablePacketDebug", - false, - "When enabled, a ring-buffer of 'packetDebugBufferSize' packets will be kept, and dumped when exceptions are thrown in key areas in the driver's code", - "3.1.3", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty enableQueryTimeouts = new BooleanConnectionProperty( - "enableQueryTimeouts", - true, - "When enabled, query timeouts set via Statement.setQueryTimeout() use a shared " - + "java.util.Timer instance for scheduling. Even if the timeout doesn't expire before the query is processed, there will be " - + "memory used by the TimerTask for the given timeout which won't be reclaimed until " - + "the time the timeout would have expired if it hadn't been cancelled by the driver. High-load environments " - + "might want to consider disabling this functionality.", - "5.0.6", - PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty explainSlowQueries = new BooleanConnectionProperty( - "explainSlowQueries", - false, - "If 'logSlowQueries' is enabled, should the driver automatically issue an 'EXPLAIN' on the" - + " server and send the results to the configured log at a WARN level?", - "3.1.2", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - /** When failed-over, set connection to read-only? */ - private BooleanConnectionProperty failOverReadOnly = new BooleanConnectionProperty( - "failOverReadOnly", - true, - "When failing over in autoReconnect mode, should the connection be set to 'read-only'?", - "3.0.12", HA_CATEGORY, 2); - - private BooleanConnectionProperty gatherPerformanceMetrics = new BooleanConnectionProperty( - "gatherPerfMetrics", - false, - "Should the driver gather performance metrics, and report them via the configured logger every 'reportMetricsIntervalMillis' milliseconds?", - "3.1.2", DEBUGING_PROFILING_CATEGORY, 1); - - private BooleanConnectionProperty generateSimpleParameterMetadata = new BooleanConnectionProperty( - "generateSimpleParameterMetadata", false, "Should the driver generate simplified parameter metadata for PreparedStatements when " - + "no metadata is available either because the server couldn't support preparing the statement, or server-side prepared statements" + - " are disabled?" - , "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); - - private boolean highAvailabilityAsBoolean = false; - - private BooleanConnectionProperty holdResultsOpenOverStatementClose = new BooleanConnectionProperty( - "holdResultsOpenOverStatementClose", - false, - "Should the driver close result sets on Statement.close() as required by the JDBC specification?", - "3.1.7", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty includeInnodbStatusInDeadlockExceptions = new BooleanConnectionProperty( - "includeInnodbStatusInDeadlockExceptions", - false, - "Include the output of \"SHOW ENGINE INNODB STATUS\" in exception messages when deadlock exceptions are detected?", - "5.0.7", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty ignoreNonTxTables = new BooleanConnectionProperty( - "ignoreNonTxTables", - false, - "Ignore non-transactional table warning for rollback? (defaults to 'false').", - "3.0.9", MISC_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty initialTimeout = new IntegerConnectionProperty( - "initialTimeout", 2, 1, Integer.MAX_VALUE, - "If autoReconnect is enabled, the" - + " initial time to wait between" - + " re-connect attempts (in seconds, defaults to '2').", - "1.1", HA_CATEGORY, 5); - - private BooleanConnectionProperty isInteractiveClient = new BooleanConnectionProperty( - "interactiveClient", - false, - "Set the CLIENT_INTERACTIVE flag, which tells MySQL " - + "to timeout connections based on INTERACTIVE_TIMEOUT instead of WAIT_TIMEOUT", - "3.1.0", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty jdbcCompliantTruncation = new BooleanConnectionProperty( - "jdbcCompliantTruncation", - true, - "Should the driver throw java.sql.DataTruncation" - + " exceptions when data is truncated as is required by the JDBC specification when connected to a server that supports warnings" - + "(MySQL 4.1.0 and newer)?", "3.1.2", MISC_CATEGORY, - Integer.MIN_VALUE); - - private boolean jdbcCompliantTruncationForReads = - this.jdbcCompliantTruncation.getValueAsBoolean(); - - private StringConnectionProperty loadBalanceStrategy = new StringConnectionProperty( - "loadBalanceStrategy", - "random", - new String[] {"random", "bestResponseTime"}, - "If using a load-balanced connection to connect to SQL nodes in a MySQL Cluster/NDB configuration" + - "(by using the URL prefix \"jdbc:mysql:loadbalance://\"), which load balancin algorithm should the driver " + - "use: (1) \"random\" - the driver will pick a random host for each request. This tends " + - "to work better than round-robin, as the randomness will somewhat account for " + - "spreading loads where requests vary in response time, while round-robin " + - "can sometimes lead to overloaded nodes if there are variations in response times " + - "across the workload. (2) \"bestResponseTime\" - the driver will route the request to the host that had " + - "the best response time for the previous transaction.", - "5.0.6", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty localSocketAddress = new StringConnectionProperty("localSocketAddress", - null, "Hostname or IP address given to explicitly configure the interface that " - + "the driver will bind the client side of the TCP/IP connection to when connecting.", - "5.0.5", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); - - private MemorySizeConnectionProperty locatorFetchBufferSize = new MemorySizeConnectionProperty( - "locatorFetchBufferSize", - 1024 * 1024, - 0, - Integer.MAX_VALUE, - "If 'emulateLocators' is configured to 'true', what size " - + " buffer should be used when fetching BLOB data for getBinaryInputStream?", - "3.2.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty loggerClassName = new StringConnectionProperty( - "logger", STANDARD_LOGGER_NAME, - "The name of a class that implements '" + Log.class.getName() - + "' that will be used to log messages to." - + "(default is '" + STANDARD_LOGGER_NAME + "', which " - + "logs to STDERR)", "3.1.1", DEBUGING_PROFILING_CATEGORY, - 0); - - private BooleanConnectionProperty logSlowQueries = new BooleanConnectionProperty( - "logSlowQueries", - false, - "Should queries that take longer than 'slowQueryThresholdMillis' be logged?", - "3.1.2", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty logXaCommands = new BooleanConnectionProperty( - "logXaCommands", - false, - "Should the driver log XA commands sent by MysqlXaConnection to the server," + - " at the DEBUG level of logging?", - "5.0.5", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty maintainTimeStats = new BooleanConnectionProperty( - "maintainTimeStats", - true, - "Should the driver maintain various internal timers to enable " - + "idle time calculations as well as more verbose error messages when " - + "the connection to the server fails? Setting this property to " - + "false removes at least two calls to System.getCurrentTimeMillis() " - + "per query.", "3.1.9", PERFORMANCE_CATEGORY, - Integer.MAX_VALUE); - - private boolean maintainTimeStatsAsBoolean = true; - - private IntegerConnectionProperty maxQuerySizeToLog = new IntegerConnectionProperty( - "maxQuerySizeToLog", - 2048, - 0, - Integer.MAX_VALUE, - "Controls the maximum length/size of a query that will get logged when profiling or tracing", - "3.1.3", DEBUGING_PROFILING_CATEGORY, 4); - - private IntegerConnectionProperty maxReconnects = new IntegerConnectionProperty( - "maxReconnects", - 3, - 1, - Integer.MAX_VALUE, - "Maximum number of reconnects to attempt if autoReconnect is true, default is '3'.", - "1.1", HA_CATEGORY, 4); - - private IntegerConnectionProperty maxRows = new IntegerConnectionProperty( - "maxRows", -1, -1, Integer.MAX_VALUE, - "The maximum number of rows to return " - + " (0, the default means return all rows).", - "all versions", MISC_CATEGORY, Integer.MIN_VALUE); - - private int maxRowsAsInt = -1; - - private IntegerConnectionProperty metadataCacheSize = new IntegerConnectionProperty( - "metadataCacheSize", - 50, - 1, - Integer.MAX_VALUE, - "The number of queries to cache" - + "ResultSetMetadata for if cacheResultSetMetaData is set to 'true' (default 50)", - "3.1.1", PERFORMANCE_CATEGORY, 5); - - private BooleanConnectionProperty noAccessToProcedureBodies = new BooleanConnectionProperty( - "noAccessToProcedureBodies", - false, - "When determining procedure parameter types for CallableStatements, and the connected user " - + " can't access procedure bodies through \"SHOW CREATE PROCEDURE\" or select on mysql.proc " - + " should the driver instead create basic metadata (all parameters reported as IN VARCHARs," - + " but allowing registerOutParameter() to be called on them anyway) instead " - + " of throwing an exception?", - "5.0.3", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty noDatetimeStringSync = new BooleanConnectionProperty( - "noDatetimeStringSync", - false, - "Don't ensure that ResultSet.getDatetimeType().toString().equals(ResultSet.getString())", - "3.1.7", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty noTimezoneConversionForTimeType = new BooleanConnectionProperty( - "noTimezoneConversionForTimeType", - false, - "Don't convert TIME values using the server timezone if 'useTimezone'='true'", - "5.0.0", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty nullCatalogMeansCurrent = new BooleanConnectionProperty( - "nullCatalogMeansCurrent", - true, - "When DatabaseMetadataMethods ask for a 'catalog' parameter, does the value null mean use the current catalog? " - + "(this is not JDBC-compliant, but follows legacy behavior from earlier versions of the driver)", - "3.1.8", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty nullNamePatternMatchesAll = new BooleanConnectionProperty( - "nullNamePatternMatchesAll", - true, - "Should DatabaseMetaData methods that accept *pattern parameters treat null the same as '%' " - + " (this is not JDBC-compliant, however older versions of the driver accepted this departure from the specification)", - "3.1.8", MISC_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty packetDebugBufferSize = new IntegerConnectionProperty( - "packetDebugBufferSize", - 20, - 0, - Integer.MAX_VALUE, - "The maximum number of packets to retain when 'enablePacketDebug' is true", - "3.1.3", DEBUGING_PROFILING_CATEGORY, 7); - - private BooleanConnectionProperty padCharsWithSpace = new BooleanConnectionProperty( - "padCharsWithSpace", - false, - "If a result set column has the CHAR type and the value does not fill the " - + "amount of characters specified in the DDL for the column, should the driver " - + "pad the remaining characters with space (for ANSI compliance)?", - "5.0.6", - MISC_CATEGORY, - Integer.MIN_VALUE); - - private BooleanConnectionProperty paranoid = new BooleanConnectionProperty( - "paranoid", - false, - "Take measures to prevent exposure sensitive information in error messages and clear " - + "data structures holding sensitive data when possible? (defaults to 'false')", - "3.0.1", SECURITY_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty pedantic = new BooleanConnectionProperty( - "pedantic", false, "Follow the JDBC spec to the letter.", "3.0.0", - MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty pinGlobalTxToPhysicalConnection = new BooleanConnectionProperty( - "pinGlobalTxToPhysicalConnection", false, "When using XAConnections, should the driver ensure that " - + " operations on a given XID are always routed to the same physical connection? This allows the XAConnection" - + " to support \"XA START ... JOIN\" after \"XA END\" has been called", - "5.0.1", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty populateInsertRowWithDefaultValues = new BooleanConnectionProperty( - "populateInsertRowWithDefaultValues", false, - "When using ResultSets that are CONCUR_UPDATABLE, should the driver pre-poulate " + - "the \"insert\" row with default values from the DDL for the table used in the query " + - " so those values are immediately available for ResultSet accessors? This functionality requires a " + - " call to the database for metadata each time a result set of this type is created. " + - " If disabled (the default), the default values will be populated by the an internal" + - " call to refreshRow() which pulls back default values and/or values changed by triggers.", - "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty preparedStatementCacheSize = new IntegerConnectionProperty( - "prepStmtCacheSize", 25, 0, Integer.MAX_VALUE, - "If prepared statement caching is enabled, " - + "how many prepared statements should be cached?", - "3.0.10", PERFORMANCE_CATEGORY, 10); - - private IntegerConnectionProperty preparedStatementCacheSqlLimit = new IntegerConnectionProperty( - "prepStmtCacheSqlLimit", - 256, - 1, - Integer.MAX_VALUE, - "If prepared statement caching is enabled, " - + "what's the largest SQL the driver will cache the parsing for?", - "3.0.10", PERFORMANCE_CATEGORY, 11); - - private BooleanConnectionProperty processEscapeCodesForPrepStmts = - new BooleanConnectionProperty("processEscapeCodesForPrepStmts", - true, - "Should the driver process escape codes in queries that are prepared?", - "3.1.12", - MISC_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty profileSql = new StringConnectionProperty( - "profileSql", - null, - "Deprecated, use 'profileSQL' instead. Trace queries and their execution/fetch times on STDERR (true/false) defaults to 'false'", - "2.0.14", DEBUGING_PROFILING_CATEGORY, 3); - - private BooleanConnectionProperty profileSQL = new BooleanConnectionProperty( - "profileSQL", - false, - "Trace queries and their execution/fetch times to the configured logger (true/false) defaults to 'false'", - "3.1.0", DEBUGING_PROFILING_CATEGORY, 1); - - private boolean profileSQLAsBoolean = false; - - private StringConnectionProperty propertiesTransform = new StringConnectionProperty( - NonRegisteringDriver.PROPERTIES_TRANSFORM_KEY, - null, - "An implementation of com.mysql.jdbc.ConnectionPropertiesTransform that the driver will use to modify URL properties passed to the driver before attempting a connection", - "3.1.4", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty queriesBeforeRetryMaster = new IntegerConnectionProperty( - "queriesBeforeRetryMaster", - 50, - 1, - Integer.MAX_VALUE, - "Number of queries to issue before falling back to master when failed over " - + "(when using multi-host failover). Whichever condition is met first, " - + "'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an " - + "attempt to be made to reconnect to the master. Defaults to 50.", - "3.0.2", HA_CATEGORY, 7); - - private BooleanConnectionProperty reconnectAtTxEnd = new BooleanConnectionProperty( - "reconnectAtTxEnd", false, - "If autoReconnect is set to true, should the driver attempt reconnections" - + "at the end of every transaction?", "3.0.10", - HA_CATEGORY, 4); - - private boolean reconnectTxAtEndAsBoolean = false; - - private BooleanConnectionProperty relaxAutoCommit = new BooleanConnectionProperty( - "relaxAutoCommit", - false, - "If the version of MySQL the driver connects to does not support transactions, still allow calls to commit(), rollback() and setAutoCommit() (true/false, defaults to 'false')?", - "2.0.13", MISC_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty reportMetricsIntervalMillis = new IntegerConnectionProperty( - "reportMetricsIntervalMillis", - 30000, - 0, - Integer.MAX_VALUE, - "If 'gatherPerfMetrics' is enabled, how often should they be logged (in ms)?", - "3.1.2", DEBUGING_PROFILING_CATEGORY, 3); - - private BooleanConnectionProperty requireSSL = new BooleanConnectionProperty( - "requireSSL", false, - "Require SSL connection if useSSL=true? (defaults to 'false').", - "3.1.0", SECURITY_CATEGORY, 3); - - private StringConnectionProperty resourceId = new StringConnectionProperty( - "resourceId", - null, "A globally unique name that identifies the resource that this datasource or connection is " + - "connected to, used for XAResource.isSameRM() when the driver can't determine this value based on " + - "hostnames used in the URL", - "5.0.1", - HA_CATEGORY, - Integer.MIN_VALUE); - - private IntegerConnectionProperty resultSetSizeThreshold = new IntegerConnectionProperty("resultSetSizeThreshold", 100, - "If the usage advisor is enabled, how many rows should a result set contain before the driver warns that it " - + " is suspiciously large?", "5.0.5", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty retainStatementAfterResultSetClose = new BooleanConnectionProperty( - "retainStatementAfterResultSetClose", - false, - "Should the driver retain the Statement reference in a ResultSet after ResultSet.close()" - + " has been called. This is not JDBC-compliant after JDBC-4.0.", - "3.1.11", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty rewriteBatchedStatements = new BooleanConnectionProperty( - "rewriteBatchedStatements", - false, - "Should the driver use multiqueries (irregardless of the setting of \"allowMultiQueries\") as well as " - + "rewriting of prepared statements for INSERT and REPLACE into multi-value inserts/replaces when executeBatch() is called? Notice that this has the potential " - + "for SQL injection if using plain java.sql.Statements and your code doesn't sanitize input correctly.\n\n" - + "Notice that if you don't specify stream lengths when using PreparedStatement.set*Stream()," - + "the driver won't be able to determine the optimium number of parameters per batch and you might receive " - + "an error from the driver that the resultant packet is too large.\n\n" - + "Statement.getGeneratedKeys() for these rewritten statements only works when the entire " - + "batch includes INSERT statements.", - "3.1.13", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty rollbackOnPooledClose = new BooleanConnectionProperty( - "rollbackOnPooledClose", - true, - "Should the driver issue a rollback() when the logical connection in a pool is closed?", - "3.0.15", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty roundRobinLoadBalance = new BooleanConnectionProperty( - "roundRobinLoadBalance", - false, - "When autoReconnect is enabled, and failoverReadonly is false, should we pick hosts to connect to on a round-robin basis?", - "3.1.2", HA_CATEGORY, 5); - - private BooleanConnectionProperty runningCTS13 = new BooleanConnectionProperty( - "runningCTS13", - false, - "Enables workarounds for bugs in Sun's JDBC compliance testsuite version 1.3", - "3.1.7", MISC_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty secondsBeforeRetryMaster = new IntegerConnectionProperty( - "secondsBeforeRetryMaster", - 30, - 1, - Integer.MAX_VALUE, - "How long should the driver wait, when failed over, before attempting " - + "to reconnect to the master server? Whichever condition is met first, " - + "'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an " - + "attempt to be made to reconnect to the master. Time in seconds, defaults to 30", - "3.0.2", HA_CATEGORY, 8); - - private StringConnectionProperty serverTimezone = new StringConnectionProperty( - "serverTimezone", - null, - "Override detection/mapping of timezone. Used when timezone from server doesn't map to Java timezone", - "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty sessionVariables = new StringConnectionProperty( - "sessionVariables", null, - "A comma-separated list of name/value pairs to be sent as SET SESSION ... to " - + " the server when the driver connects.", "3.1.8", - MISC_CATEGORY, Integer.MAX_VALUE); - - private IntegerConnectionProperty slowQueryThresholdMillis = new IntegerConnectionProperty( - "slowQueryThresholdMillis", - 2000, - 0, - Integer.MAX_VALUE, - "If 'logSlowQueries' is enabled, how long should a query (in ms) before it is logged as 'slow'?", - "3.1.2", DEBUGING_PROFILING_CATEGORY, 9); - - private LongConnectionProperty slowQueryThresholdNanos = new LongConnectionProperty( - "slowQueryThresholdNanos", - 0, - "If 'useNanosForElapsedTime' is set to true, and this property is set to a non-zero value," - + " the driver will use this threshold (in nanosecond units) to determine if a query was slow.", - "5.0.7", - DEBUGING_PROFILING_CATEGORY, - 10); - - private StringConnectionProperty socketFactoryClassName = new StringConnectionProperty( - "socketFactory", - StandardSocketFactory.class.getName(), - "The name of the class that the driver should use for creating socket connections to the server. This class must implement the interface 'com.mysql.jdbc.SocketFactory' and have public no-args constructor.", - "3.0.3", CONNECTION_AND_AUTH_CATEGORY, 4); - - private IntegerConnectionProperty socketTimeout = new IntegerConnectionProperty( - "socketTimeout", - 0, - 0, - Integer.MAX_VALUE, - "Timeout on network socket operations (0, the default means no timeout).", - "3.0.1", CONNECTION_AND_AUTH_CATEGORY, 10); - - private BooleanConnectionProperty strictFloatingPoint = new BooleanConnectionProperty( - "strictFloatingPoint", false, - "Used only in older versions of compliance test", "3.0.0", - MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty strictUpdates = new BooleanConnectionProperty( - "strictUpdates", - true, - "Should the driver do strict checking (all primary keys selected) of updatable result sets (true, false, defaults to 'true')?", - "3.0.4", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty overrideSupportsIntegrityEnhancementFacility = - new BooleanConnectionProperty("overrideSupportsIntegrityEnhancementFacility", - false, - "Should the driver return \"true\" for DatabaseMetaData.supportsIntegrityEnhancementFacility() " - + "even if the database doesn't support it to workaround applications that require this method to return " - + "\"true\" to signal support of foreign keys, even though the SQL specification states that this facility " - + "contains much more than just foreign key support (one such application being OpenOffice)?", - "3.1.12", MISC_CATEGORY, Integer.MIN_VALUE); - private BooleanConnectionProperty tcpNoDelay = new BooleanConnectionProperty( - StandardSocketFactory.TCP_NO_DELAY_PROPERTY_NAME, - Boolean.valueOf(StandardSocketFactory.TCP_NO_DELAY_DEFAULT_VALUE).booleanValue(), - "If connecting using TCP/IP, should the driver set SO_TCP_NODELAY (disabling the Nagle Algorithm)?", - "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty tcpKeepAlive = new BooleanConnectionProperty( - StandardSocketFactory.TCP_KEEP_ALIVE_PROPERTY_NAME, - Boolean.valueOf(StandardSocketFactory.TCP_KEEP_ALIVE_DEFAULT_VALUE).booleanValue(), - "If connecting using TCP/IP, should the driver set SO_KEEPALIVE?", - "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty tcpRcvBuf = new IntegerConnectionProperty( - StandardSocketFactory.TCP_RCV_BUF_PROPERTY_NAME, - Integer.parseInt(StandardSocketFactory.TCP_RCV_BUF_DEFAULT_VALUE), - 0, Integer.MAX_VALUE, - "If connecting using TCP/IP, should the driver set SO_RCV_BUF to the given value? " - + "The default value of '0', means use the platform default value for this property)", - "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty tcpSndBuf = new IntegerConnectionProperty( - StandardSocketFactory.TCP_SND_BUF_PROPERTY_NAME, - Integer.parseInt(StandardSocketFactory.TCP_SND_BUF_DEFAULT_VALUE), - 0, Integer.MAX_VALUE, - "If connecting using TCP/IP, shuold the driver set SO_SND_BUF to the given value? " - + "The default value of '0', means use the platform default value for this property)", - "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); - - private IntegerConnectionProperty tcpTrafficClass = new IntegerConnectionProperty( - StandardSocketFactory.TCP_TRAFFIC_CLASS_PROPERTY_NAME, - Integer.parseInt(StandardSocketFactory.TCP_TRAFFIC_CLASS_DEFAULT_VALUE), - 0, 255, - "If connecting using TCP/IP, should the driver set traffic class or type-of-service fields ?" + - " See the documentation for java.net.Socket.setTrafficClass() for more information.", - "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty tinyInt1isBit = new BooleanConnectionProperty( - "tinyInt1isBit", - true, - "Should the driver treat the datatype TINYINT(1) as the BIT type " - + "(because the server silently converts BIT -> TINYINT(1) when creating tables)?", - "3.0.16", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty traceProtocol = new BooleanConnectionProperty( - "traceProtocol", false, - "Should trace-level network protocol be logged?", "3.1.2", - DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty treatUtilDateAsTimestamp = new BooleanConnectionProperty( - "treatUtilDateAsTimestamp", true, - "Should the driver treat java.util.Date as a TIMESTAMP for the purposes of PreparedStatement.setObject()?", - "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty transformedBitIsBoolean = new BooleanConnectionProperty( - "transformedBitIsBoolean", - false, - "If the driver converts TINYINT(1) to a different type, should it use BOOLEAN instead of BIT " - + " for future compatibility with MySQL-5.0, as MySQL-5.0 has a BIT type?", - "3.1.9", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useCompression = new BooleanConnectionProperty( - "useCompression", - false, - "Use zlib compression when communicating with the server (true/false)? Defaults to 'false'.", - "3.0.17", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty useConfigs = new StringConnectionProperty( - "useConfigs", - null, - "Load the comma-delimited list of configuration properties before parsing the " - + "URL or applying user-specified properties. These configurations are explained in the 'Configurations' of the documentation.", - "3.1.5", CONNECTION_AND_AUTH_CATEGORY, Integer.MAX_VALUE); - - private BooleanConnectionProperty useCursorFetch = new BooleanConnectionProperty( - "useCursorFetch", - false, - "If connected to MySQL > 5.0.2, and setFetchSize() > 0 on a statement, should " - + " that statement use cursor-based fetching to retrieve rows?", - "5.0.0", PERFORMANCE_CATEGORY, Integer.MAX_VALUE); - - private BooleanConnectionProperty useDynamicCharsetInfo = new BooleanConnectionProperty( - "useDynamicCharsetInfo", - true, - "Should the driver use a per-connection cache of character set information queried from the " - + " server when necessary, or use a built-in static mapping that is more efficient, but isn't " - + " aware of custom character sets or character sets implemented after the release of the JDBC driver?" - + "(this only affects the \"padCharsWithSpace\" configuration property and the " - + "ResultSetMetaData.getColumnDisplayWidth() method)." - , "5.0.6", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useFastIntParsing = new BooleanConnectionProperty( - "useFastIntParsing", - true, - "Use internal String->Integer conversion routines to avoid excessive object creation?", - "3.1.4", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useFastDateParsing = new BooleanConnectionProperty( - "useFastDateParsing", - true, - "Use internal String->Date/Time/Teimstamp conversion routines to avoid excessive object creation?", - "5.0.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useHostsInPrivileges = new BooleanConnectionProperty( - "useHostsInPrivileges", - true, - "Add '@hostname' to users in DatabaseMetaData.getColumn/TablePrivileges() (true/false), defaults to 'true'.", - "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); - private BooleanConnectionProperty useInformationSchema = new BooleanConnectionProperty( - "useInformationSchema", - false, - "When connected to MySQL-5.0.7 or newer, should the driver use the INFORMATION_SCHEMA to " - + " derive information used by DatabaseMetaData?", - "5.0.0", MISC_CATEGORY, Integer.MIN_VALUE); - private BooleanConnectionProperty useJDBCCompliantTimezoneShift = new BooleanConnectionProperty( - "useJDBCCompliantTimezoneShift", - false, - "Should the driver use JDBC-compliant rules when converting TIME/TIMESTAMP/DATETIME values' timezone information " + - "for those JDBC arguments which take a java.util.Calendar argument? (Notice that this " + - "option is exclusive of the \"useTimezone=true\" configuration option.)", - "5.0.0", - MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useLocalSessionState = new BooleanConnectionProperty( - "useLocalSessionState", - false, - "Should the driver refer to the internal values of autocommit and transaction isolation that are set " - + "by Connection.setAutoCommit() and Connection.setTransactionIsolation() and transaction state " - + "as maintained by the protocol, rather than querying the database or blindly " - + "sending commands to the database for commit() or rollback() method calls?", - "3.1.7", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useNanosForElapsedTime = new BooleanConnectionProperty( - "useNanosForElapsedTime", - false, - "For profiling/debugging functionality that measures elapsed time, should the driver " - + "try to use nanoseconds resolution if available (JDK >= 1.5)?", - "5.0.7", - DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useOldAliasMetadataBehavior = new BooleanConnectionProperty( - "useOldAliasMetadataBehavior", - true, - "Should the driver use the legacy behavior for \"AS\" clauses on columns and tables, and only " - + "return aliases (if any) for ResultSetMetaData.getColumnName() or ResultSetMetaData.getTableName() " - + "rather than the original column/table name?", - "5.0.4", - MISC_CATEGORY, - Integer.MIN_VALUE); - - private BooleanConnectionProperty useOldUTF8Behavior = new BooleanConnectionProperty( - "useOldUTF8Behavior", - false, - "Use the UTF-8 behavior the driver did when communicating with 4.0 and older servers", - "3.1.6", MISC_CATEGORY, Integer.MIN_VALUE); - - private boolean useOldUTF8BehaviorAsBoolean = false; - - private BooleanConnectionProperty useOnlyServerErrorMessages = new BooleanConnectionProperty( - "useOnlyServerErrorMessages", - true, - "Don't prepend 'standard' SQLState error messages to error messages returned by the server.", - "3.0.15", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useReadAheadInput = new BooleanConnectionProperty( - "useReadAheadInput", - true, - "Use newer, optimized non-blocking, buffered input stream when reading from the server?", - "3.1.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useSqlStateCodes = new BooleanConnectionProperty( - "useSqlStateCodes", - true, - "Use SQL Standard state codes instead of 'legacy' X/Open/SQL state codes (true/false), default is 'true'", - "3.1.3", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useSSL = new BooleanConnectionProperty( - "useSSL", - false, - "Use SSL when communicating with the server (true/false), defaults to 'false'", - "3.0.2", SECURITY_CATEGORY, 2); - - private BooleanConnectionProperty useSSPSCompatibleTimezoneShift = new BooleanConnectionProperty( - "useSSPSCompatibleTimezoneShift", - false, - "If migrating from an environment that was using server-side prepared statements, and the" - + " configuration property \"useJDBCCompliantTimeZoneShift\" set to \"true\", use compatible behavior" - + " when not using server-side prepared statements when sending TIMESTAMP values to the MySQL server.", - "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useStreamLengthsInPrepStmts = new BooleanConnectionProperty( - "useStreamLengthsInPrepStmts", - true, - "Honor stream length parameter in " - + "PreparedStatement/ResultSet.setXXXStream() method calls (true/false, defaults to 'true')?", - "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useTimezone = new BooleanConnectionProperty( - "useTimezone", - false, - "Convert time/date types between client and server timezones (true/false, defaults to 'false')?", - "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useUltraDevWorkAround = new BooleanConnectionProperty( - "ultraDevHack", - false, - "Create PreparedStatements for prepareCall() when required, because UltraDev " - + " is broken and issues a prepareCall() for _all_ statements? (true/false, defaults to 'false')", - "2.0.3", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useUnbufferedInput = new BooleanConnectionProperty( - "useUnbufferedInput", true, - "Don't use BufferedInputStream for reading data from the server", - "3.0.11", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useUnicode = new BooleanConnectionProperty( - "useUnicode", - true, - "Should the driver use Unicode character encodings when handling strings? Should only be used when the driver can't determine the character set mapping, or you are trying to 'force' the driver to use a character set that MySQL either doesn't natively support (such as UTF-8), true/false, defaults to 'true'", - "1.1g", MISC_CATEGORY, 0); - - // Cache these values, they are 'hot' - private boolean useUnicodeAsBoolean = true; - - private BooleanConnectionProperty useUsageAdvisor = new BooleanConnectionProperty( - "useUsageAdvisor", - false, - "Should the driver issue 'usage' warnings advising proper and efficient usage of JDBC and MySQL Connector/J to the log (true/false, defaults to 'false')?", - "3.1.1", DEBUGING_PROFILING_CATEGORY, 10); - - private boolean useUsageAdvisorAsBoolean = false; - - private BooleanConnectionProperty yearIsDateType = new BooleanConnectionProperty( - "yearIsDateType", - true, - "Should the JDBC driver treat the MySQL type \"YEAR\" as a java.sql.Date, or as a SHORT?", - "3.1.9", MISC_CATEGORY, Integer.MIN_VALUE); - - private StringConnectionProperty zeroDateTimeBehavior = new StringConnectionProperty( - "zeroDateTimeBehavior", - ZERO_DATETIME_BEHAVIOR_EXCEPTION, - new String[] { ZERO_DATETIME_BEHAVIOR_EXCEPTION, - ZERO_DATETIME_BEHAVIOR_ROUND, - ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL }, - "What should happen when the driver encounters DATETIME values that are composed " - + "entirely of zeroes (used by MySQL to represent invalid dates)? " - + "Valid values are '" - + ZERO_DATETIME_BEHAVIOR_EXCEPTION - + "', '" - + ZERO_DATETIME_BEHAVIOR_ROUND - + "' and '" - + ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + "'.", "3.1.4", - MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useJvmCharsetConverters = new BooleanConnectionProperty("useJvmCharsetConverters", - false, "Always use the character encoding routines built into the JVM, rather than using " - + "lookup tables for single-byte character sets?", "5.0.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty useGmtMillisForDatetimes = new BooleanConnectionProperty("useGmtMillisForDatetimes", false, "Convert between session timezone and GMT before creating Date and Timestamp instances (value of \"false\" is legacy behavior, \"true\" leads to more JDBC-compliant behavior.", "3.1.12", MISC_CATEGORY, Integer.MIN_VALUE); - - private BooleanConnectionProperty dumpMetadataOnColumnNotFound = new BooleanConnectionProperty("dumpMetadataOnColumnNotFound", false, "Should the driver dump the field-level metadata of a result set into " + "the exception message when ResultSet.findColumn() fails?", "3.1.13", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); - - protected DriverPropertyInfo[] exposeAsDriverPropertyInfoInternal( - Properties info, int slotsToReserve) throws SQLException { - initializeProperties(info); - - int numProperties = PROPERTY_LIST.size(); - - int listSize = numProperties + slotsToReserve; - - DriverPropertyInfo[] driverProperties = new DriverPropertyInfo[listSize]; - - for (int i = slotsToReserve; i < listSize; i++) { - java.lang.reflect.Field propertyField = (java.lang.reflect.Field) PROPERTY_LIST - .get(i - slotsToReserve); - - try { - ConnectionProperty propToExpose = (ConnectionProperty) propertyField - .get(this); - - if (info != null) { - propToExpose.initializeFrom(info); - } - - - driverProperties[i] = propToExpose.getAsDriverPropertyInfo(); - } catch (IllegalAccessException iae) { - throw SQLError.createSQLException("Internal properties failure", - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - return driverProperties; - } - - protected Properties exposeAsProperties(Properties info) - throws SQLException { - if (info == null) { - info = new Properties(); - } - - int numPropertiesToSet = PROPERTY_LIST.size(); - - for (int i = 0; i < numPropertiesToSet; i++) { - java.lang.reflect.Field propertyField = (java.lang.reflect.Field) PROPERTY_LIST - .get(i); - - try { - ConnectionProperty propToGet = (ConnectionProperty) propertyField - .get(this); - - Object propValue = propToGet.getValueAsObject(); - - if (propValue != null) { - info.setProperty(propToGet.getPropertyName(), propValue - .toString()); - } - } catch (IllegalAccessException iae) { - throw SQLError.createSQLException("Internal properties failure", - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - return info; - } - - /** * Returns a description of the connection properties as an XML document. - * + * * @return the connection properties as an XML document. * @throws SQLException * if an error occurs. */ - public String exposeAsXml() throws SQLException { - StringBuffer xmlBuf = new StringBuffer(); - xmlBuf.append(""); + public abstract String exposeAsXml() throws SQLException; - int numPropertiesToSet = PROPERTY_LIST.size(); - - int numCategories = PROPERTY_CATEGORIES.length; - - Map propertyListByCategory = new HashMap(); - - for (int i = 0; i < numCategories; i++) { - propertyListByCategory.put(PROPERTY_CATEGORIES[i], new Map[] { - new TreeMap(), new TreeMap() }); - } - - // - // The following properties are not exposed as 'normal' properties, but - // they are - // settable nonetheless, so we need to have them documented, make sure - // that they sort 'first' as #1 and #2 in the category - // - StringConnectionProperty userProp = new StringConnectionProperty( - NonRegisteringDriver.USER_PROPERTY_KEY, null, - "The user to connect as", "all", CONNECTION_AND_AUTH_CATEGORY, - Integer.MIN_VALUE + 1); - StringConnectionProperty passwordProp = new StringConnectionProperty( - NonRegisteringDriver.PASSWORD_PROPERTY_KEY, null, - "The password to use when connecting", "all", - CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE + 2); - - Map[] connectionSortMaps = (Map[]) propertyListByCategory - .get(CONNECTION_AND_AUTH_CATEGORY); - TreeMap userMap = new TreeMap(); - userMap.put(userProp.getPropertyName(), userProp); - - connectionSortMaps[0].put(new Integer(userProp.getOrder()), userMap); - - TreeMap passwordMap = new TreeMap(); - passwordMap.put(passwordProp.getPropertyName(), passwordProp); - - connectionSortMaps[0] - .put(new Integer(passwordProp.getOrder()), passwordMap); - - try { - for (int i = 0; i < numPropertiesToSet; i++) { - java.lang.reflect.Field propertyField = (java.lang.reflect.Field) PROPERTY_LIST - .get(i); - ConnectionProperty propToGet = (ConnectionProperty) propertyField - .get(this); - Map[] sortMaps = (Map[]) propertyListByCategory.get(propToGet - .getCategoryName()); - int orderInCategory = propToGet.getOrder(); - - if (orderInCategory == Integer.MIN_VALUE) { - sortMaps[1].put(propToGet.getPropertyName(), propToGet); - } else { - Integer order = new Integer(orderInCategory); - - Map orderMap = (Map)sortMaps[0].get(order); - - if (orderMap == null) { - orderMap = new TreeMap(); - sortMaps[0].put(order, orderMap); - } - - orderMap.put(propToGet.getPropertyName(), propToGet); - } - } - - for (int j = 0; j < numCategories; j++) { - Map[] sortMaps = (Map[]) propertyListByCategory - .get(PROPERTY_CATEGORIES[j]); - Iterator orderedIter = sortMaps[0].values().iterator(); - Iterator alphaIter = sortMaps[1].values().iterator(); - - xmlBuf.append("\n "); - - while (orderedIter.hasNext()) { - Iterator orderedAlphaIter = ((Map)orderedIter.next()).values().iterator(); - - while (orderedAlphaIter.hasNext()) { - ConnectionProperty propToGet = (ConnectionProperty) orderedAlphaIter - .next(); - - xmlBuf.append("\n \n"); - xmlBuf.append(" "); - xmlBuf.append(propToGet.description); - xmlBuf.append("\n "); - } - } - - while (alphaIter.hasNext()) { - ConnectionProperty propToGet = (ConnectionProperty) alphaIter - .next(); - - xmlBuf.append("\n \n"); - xmlBuf.append(" "); - xmlBuf.append(propToGet.description); - xmlBuf.append("\n "); - } - - xmlBuf.append("\n "); - } - } catch (IllegalAccessException iae) { - throw SQLError.createSQLException("Internal properties failure", - SQLError.SQL_STATE_GENERAL_ERROR); - } - - xmlBuf.append("\n"); - - return xmlBuf.toString(); - } - /** * DOCUMENT ME! - * + * * @return */ - public boolean getAllowLoadLocalInfile() { - return this.allowLoadLocalInfile.getValueAsBoolean(); - } + public abstract boolean getAllowLoadLocalInfile(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getAllowMultiQueries() { - return this.allowMultiQueries.getValueAsBoolean(); - } + public abstract boolean getAllowMultiQueries(); /** * @return Returns the allowNanAndInf. */ - public boolean getAllowNanAndInf() { - return allowNanAndInf.getValueAsBoolean(); - } + public abstract boolean getAllowNanAndInf(); /** * @return Returns the allowUrlInLocalInfile. */ - public boolean getAllowUrlInLocalInfile() { - return this.allowUrlInLocalInfile.getValueAsBoolean(); - } + public abstract boolean getAllowUrlInLocalInfile(); /** * @return Returns the alwaysSendSetIsolation. */ - public boolean getAlwaysSendSetIsolation() { - return this.alwaysSendSetIsolation.getValueAsBoolean(); - } + public abstract boolean getAlwaysSendSetIsolation(); /** * @return Returns the autoDeserialize. */ - public boolean getAutoDeserialize() { - return autoDeserialize.getValueAsBoolean(); - } + public abstract boolean getAutoDeserialize(); - public boolean getAutoGenerateTestcaseScript() { - return this.autoGenerateTestcaseScriptAsBoolean; - } + public abstract boolean getAutoGenerateTestcaseScript(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getAutoReconnectForPools() { - return this.autoReconnectForPoolsAsBoolean; - } + public abstract boolean getAutoReconnectForPools(); /** * @return Returns the blobSendChunkSize. */ - public int getBlobSendChunkSize() { - return blobSendChunkSize.getValueAsInt(); - } + public abstract int getBlobSendChunkSize(); /** * DOCUMENT ME! - * + * * @return Returns if cacheCallableStatements is enabled */ - public boolean getCacheCallableStatements() { - return this.cacheCallableStatements.getValueAsBoolean(); - } + public abstract boolean getCacheCallableStatements(); /** * DOCUMENT ME! - * + * * @return Returns the cachePreparedStatements. */ - public boolean getCachePreparedStatements() { - return ((Boolean) this.cachePreparedStatements.getValueAsObject()) - .booleanValue(); - } + public abstract boolean getCachePreparedStatements(); /** * DOCUMENT ME! - * + * * @return DOCUMENT ME! */ - public boolean getCacheResultSetMetadata() { - return this.cacheResultSetMetaDataAsBoolean; - } + public abstract boolean getCacheResultSetMetadata(); /** * @return Returns the cacheServerConfiguration. */ - public boolean getCacheServerConfiguration() { - return cacheServerConfiguration.getValueAsBoolean(); - } + public abstract boolean getCacheServerConfiguration(); /** * DOCUMENT ME! - * + * * @return Returns the callableStatementCacheSize. */ - public int getCallableStatementCacheSize() { - return this.callableStatementCacheSize.getValueAsInt(); - } + public abstract int getCallableStatementCacheSize(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getCapitalizeTypeNames() { - return this.capitalizeTypeNames.getValueAsBoolean(); - } + public abstract boolean getCapitalizeTypeNames(); /** * DOCUMENT ME! - * + * * @return Returns the characterSetResults. */ - public String getCharacterSetResults() { - return this.characterSetResults.getValueAsString(); - } + public abstract String getCharacterSetResults(); /** * DOCUMENT ME! - * + * * @return Returns the clobberStreamingResults. */ - public boolean getClobberStreamingResults() { - return this.clobberStreamingResults.getValueAsBoolean(); - } + public abstract boolean getClobberStreamingResults(); - public String getClobCharacterEncoding() { - return this.clobCharacterEncoding.getValueAsString(); - } + public abstract String getClobCharacterEncoding(); /** * DOCUMENT ME! - * + * * @return Returns the connectionCollation. */ - public String getConnectionCollation() { - return this.connectionCollation.getValueAsString(); - } + public abstract String getConnectionCollation(); /** * DOCUMENT ME! - * + * * @return */ - public int getConnectTimeout() { - return this.connectTimeout.getValueAsInt(); - } + public abstract int getConnectTimeout(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getContinueBatchOnError() { - return this.continueBatchOnError.getValueAsBoolean(); - } + public abstract boolean getContinueBatchOnError(); - public boolean getCreateDatabaseIfNotExist() { - return this.createDatabaseIfNotExist.getValueAsBoolean(); - } + public abstract boolean getCreateDatabaseIfNotExist(); - public int getDefaultFetchSize() { - return this.defaultFetchSize.getValueAsInt(); - } + public abstract int getDefaultFetchSize(); /** * @return Returns the dontTrackOpenResources. */ - public boolean getDontTrackOpenResources() { - return this.dontTrackOpenResources.getValueAsBoolean(); - } + public abstract boolean getDontTrackOpenResources(); /** * DOCUMENT ME! - * + * * @return Returns the dumpQueriesOnException. */ - public boolean getDumpQueriesOnException() { - return this.dumpQueriesOnException.getValueAsBoolean(); - } + public abstract boolean getDumpQueriesOnException(); /** * @return Returns the dynamicCalendars. */ - public boolean getDynamicCalendars() { - return this.dynamicCalendars.getValueAsBoolean(); - } + public abstract boolean getDynamicCalendars(); /** * DOCUMENT ME! - * + * * @return Returns the elideSetAutoCommits. */ - public boolean getElideSetAutoCommits() { - return this.elideSetAutoCommits.getValueAsBoolean(); - } + public abstract boolean getElideSetAutoCommits(); - public boolean getEmptyStringsConvertToZero() { - return this.emptyStringsConvertToZero.getValueAsBoolean(); - } + public abstract boolean getEmptyStringsConvertToZero(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getEmulateLocators() { - return this.emulateLocators.getValueAsBoolean(); - } + public abstract boolean getEmulateLocators(); /** * @return Returns the emulateUnsupportedPstmts. */ - public boolean getEmulateUnsupportedPstmts() { - return this.emulateUnsupportedPstmts.getValueAsBoolean(); - } + public abstract boolean getEmulateUnsupportedPstmts(); /** * DOCUMENT ME! - * + * * @return Returns the enablePacketDebug. */ - public boolean getEnablePacketDebug() { - return this.enablePacketDebug.getValueAsBoolean(); - } + public abstract boolean getEnablePacketDebug(); /** * DOCUMENT ME! - * + * * @return */ - public String getEncoding() { - return this.characterEncodingAsString; - } + public abstract String getEncoding(); /** * DOCUMENT ME! - * + * * @return Returns the explainSlowQueries. */ - public boolean getExplainSlowQueries() { - return this.explainSlowQueries.getValueAsBoolean(); - } + public abstract boolean getExplainSlowQueries(); /** * DOCUMENT ME! - * + * * @return Returns the failOverReadOnly. */ - public boolean getFailOverReadOnly() { - return this.failOverReadOnly.getValueAsBoolean(); - } + public abstract boolean getFailOverReadOnly(); /** * DOCUMENT ME! - * + * * @return Returns the gatherPerformanceMetrics. */ - public boolean getGatherPerformanceMetrics() { - return this.gatherPerformanceMetrics.getValueAsBoolean(); - } + public abstract boolean getGatherPerformanceMetrics(); /** - * DOCUMENT ME! - * - * @return - */ - protected boolean getHighAvailability() { - return this.highAvailabilityAsBoolean; - } - - /** * @return Returns the holdResultsOpenOverStatementClose. */ - public boolean getHoldResultsOpenOverStatementClose() { - return holdResultsOpenOverStatementClose.getValueAsBoolean(); - } + public abstract boolean getHoldResultsOpenOverStatementClose(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getIgnoreNonTxTables() { - return this.ignoreNonTxTables.getValueAsBoolean(); - } + public abstract boolean getIgnoreNonTxTables(); /** * DOCUMENT ME! - * + * * @return */ - public int getInitialTimeout() { - return this.initialTimeout.getValueAsInt(); - } + public abstract int getInitialTimeout(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getInteractiveClient() { - return this.isInteractiveClient.getValueAsBoolean(); - } + public abstract boolean getInteractiveClient(); /** * DOCUMENT ME! - * + * * @return Returns the isInteractiveClient. */ - public boolean getIsInteractiveClient() { - return this.isInteractiveClient.getValueAsBoolean(); - } + public abstract boolean getIsInteractiveClient(); /** * DOCUMENT ME! - * + * * @return Returns the jdbcCompliantTruncation. */ - public boolean getJdbcCompliantTruncation() { - return this.jdbcCompliantTruncation.getValueAsBoolean(); - } + public abstract boolean getJdbcCompliantTruncation(); /** * @return Returns the dontTrackOpenResources. */ - public int getLocatorFetchBufferSize() { - return this.locatorFetchBufferSize.getValueAsInt(); - } + public abstract int getLocatorFetchBufferSize(); /** * DOCUMENT ME! - * + * * @return */ - public String getLogger() { - return this.loggerClassName.getValueAsString(); - } + public abstract String getLogger(); /** * DOCUMENT ME! - * + * * @return Returns the loggerClassName. */ - public String getLoggerClassName() { - return this.loggerClassName.getValueAsString(); - } + public abstract String getLoggerClassName(); /** * DOCUMENT ME! - * + * * @return Returns the logSlowQueries. */ - public boolean getLogSlowQueries() { - return this.logSlowQueries.getValueAsBoolean(); - } + public abstract boolean getLogSlowQueries(); - public boolean getMaintainTimeStats() { - return maintainTimeStatsAsBoolean; - } + public abstract boolean getMaintainTimeStats(); /** * DOCUMENT ME! - * + * * @return Returns the maxQuerySizeToLog. */ - public int getMaxQuerySizeToLog() { - return this.maxQuerySizeToLog.getValueAsInt(); - } + public abstract int getMaxQuerySizeToLog(); /** * DOCUMENT ME! - * + * * @return */ - public int getMaxReconnects() { - return this.maxReconnects.getValueAsInt(); - } + public abstract int getMaxReconnects(); /** * DOCUMENT ME! - * + * * @return */ - public int getMaxRows() { - return this.maxRowsAsInt; - } + public abstract int getMaxRows(); /** * Returns the number of queries that metadata can be cached if caching is * enabled. - * + * * @return the number of queries to cache metadata for. */ - public int getMetadataCacheSize() { - return this.metadataCacheSize.getValueAsInt(); - } + public abstract int getMetadataCacheSize(); /** * @return Returns the noDatetimeStringSync. */ - public boolean getNoDatetimeStringSync() { - return this.noDatetimeStringSync.getValueAsBoolean(); - } + public abstract boolean getNoDatetimeStringSync(); - public boolean getNullCatalogMeansCurrent() { - return this.nullCatalogMeansCurrent.getValueAsBoolean(); - } + public abstract boolean getNullCatalogMeansCurrent(); - public boolean getNullNamePatternMatchesAll() { - return this.nullNamePatternMatchesAll.getValueAsBoolean(); - } + public abstract boolean getNullNamePatternMatchesAll(); /** * DOCUMENT ME! - * + * * @return Returns the packetDebugBufferSize. */ - public int getPacketDebugBufferSize() { - return this.packetDebugBufferSize.getValueAsInt(); - } + public abstract int getPacketDebugBufferSize(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getParanoid() { - return this.paranoid.getValueAsBoolean(); - } + public abstract boolean getParanoid(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getPedantic() { - return this.pedantic.getValueAsBoolean(); - } + public abstract boolean getPedantic(); /** * DOCUMENT ME! - * + * * @return Returns the preparedStatementCacheSize. */ - public int getPreparedStatementCacheSize() { - return ((Integer) this.preparedStatementCacheSize.getValueAsObject()) - .intValue(); - } + public abstract int getPreparedStatementCacheSize(); /** * DOCUMENT ME! - * + * * @return Returns the preparedStatementCacheSqlLimit. */ - public int getPreparedStatementCacheSqlLimit() { - return ((Integer) this.preparedStatementCacheSqlLimit - .getValueAsObject()).intValue(); - } + public abstract int getPreparedStatementCacheSqlLimit(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getProfileSql() { - return this.profileSQLAsBoolean; - } + public abstract boolean getProfileSql(); /** * DOCUMENT ME! - * + * * @return Returns the profileSQL flag */ - public boolean getProfileSQL() { - return this.profileSQL.getValueAsBoolean(); - } + public abstract boolean getProfileSQL(); /** * @return Returns the propertiesTransform. */ - public String getPropertiesTransform() { - return this.propertiesTransform.getValueAsString(); - } + public abstract String getPropertiesTransform(); /** * DOCUMENT ME! - * + * * @return */ - public int getQueriesBeforeRetryMaster() { - return this.queriesBeforeRetryMaster.getValueAsInt(); - } + public abstract int getQueriesBeforeRetryMaster(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getReconnectAtTxEnd() { - return this.reconnectTxAtEndAsBoolean; - } + public abstract boolean getReconnectAtTxEnd(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getRelaxAutoCommit() { - return this.relaxAutoCommit.getValueAsBoolean(); - } + public abstract boolean getRelaxAutoCommit(); /** * DOCUMENT ME! - * + * * @return Returns the reportMetricsIntervalMillis. */ - public int getReportMetricsIntervalMillis() { - return this.reportMetricsIntervalMillis.getValueAsInt(); - } + public abstract int getReportMetricsIntervalMillis(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getRequireSSL() { - return this.requireSSL.getValueAsBoolean(); - } + public abstract boolean getRequireSSL(); - public boolean getRetainStatementAfterResultSetClose() { - return this.retainStatementAfterResultSetClose.getValueAsBoolean(); - } - /** * @return Returns the rollbackOnPooledClose. */ - public boolean getRollbackOnPooledClose() { - return this.rollbackOnPooledClose.getValueAsBoolean(); - } + public abstract boolean getRollbackOnPooledClose(); /** * Returns whether or not hosts will be picked in a round-robin fashion. - * + * * @return Returns the roundRobinLoadBalance property. */ - public boolean getRoundRobinLoadBalance() { - return this.roundRobinLoadBalance.getValueAsBoolean(); - } + public abstract boolean getRoundRobinLoadBalance(); /** * @return Returns the runningCTS13. */ - public boolean getRunningCTS13() { - return this.runningCTS13.getValueAsBoolean(); - } + public abstract boolean getRunningCTS13(); /** * DOCUMENT ME! - * + * * @return */ - public int getSecondsBeforeRetryMaster() { - return this.secondsBeforeRetryMaster.getValueAsInt(); - } + public abstract int getSecondsBeforeRetryMaster(); /** * Returns the 'serverTimezone' property. - * + * * @return the configured server timezone property. */ - public String getServerTimezone() { - return this.serverTimezone.getValueAsString(); - } + public abstract String getServerTimezone(); /** * @return Returns the sessionVariables. */ - public String getSessionVariables() { - return sessionVariables.getValueAsString(); - } + public abstract String getSessionVariables(); /** * DOCUMENT ME! - * + * * @return Returns the slowQueryThresholdMillis. */ - public int getSlowQueryThresholdMillis() { - return this.slowQueryThresholdMillis.getValueAsInt(); - } + public abstract int getSlowQueryThresholdMillis(); /** * DOCUMENT ME! - * + * * @return */ - public String getSocketFactoryClassName() { - return this.socketFactoryClassName.getValueAsString(); - } + public abstract String getSocketFactoryClassName(); /** * DOCUMENT ME! - * + * * @return */ - public int getSocketTimeout() { - return this.socketTimeout.getValueAsInt(); - } + public abstract int getSocketTimeout(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getStrictFloatingPoint() { - return this.strictFloatingPoint.getValueAsBoolean(); - } + public abstract boolean getStrictFloatingPoint(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getStrictUpdates() { - return this.strictUpdates.getValueAsBoolean(); - } + public abstract boolean getStrictUpdates(); /** * @return Returns the tinyInt1isBit. */ - public boolean getTinyInt1isBit() { - return this.tinyInt1isBit.getValueAsBoolean(); - } + public abstract boolean getTinyInt1isBit(); /** * DOCUMENT ME! - * + * * @return Returns the logProtocol. */ - public boolean getTraceProtocol() { - return this.traceProtocol.getValueAsBoolean(); - } + public abstract boolean getTraceProtocol(); - public boolean getTransformedBitIsBoolean() { - return this.transformedBitIsBoolean.getValueAsBoolean(); - } + public abstract boolean getTransformedBitIsBoolean(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseCompression() { - return this.useCompression.getValueAsBoolean(); - } + public abstract boolean getUseCompression(); /** * @return Returns the useFastIntParsing. */ - public boolean getUseFastIntParsing() { - return this.useFastIntParsing.getValueAsBoolean(); - } + public abstract boolean getUseFastIntParsing(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseHostsInPrivileges() { - return this.useHostsInPrivileges.getValueAsBoolean(); - } + public abstract boolean getUseHostsInPrivileges(); - public boolean getUseInformationSchema() { - return this.useInformationSchema.getValueAsBoolean(); - } + public abstract boolean getUseInformationSchema(); /** * @return Returns the useLocalSessionState. */ - public boolean getUseLocalSessionState() { - return this.useLocalSessionState.getValueAsBoolean(); - } + public abstract boolean getUseLocalSessionState(); /** * @return Returns the useOldUTF8Behavior. */ - public boolean getUseOldUTF8Behavior() { - return this.useOldUTF8BehaviorAsBoolean; - } + public abstract boolean getUseOldUTF8Behavior(); /** * @return Returns the useOnlyServerErrorMessages. */ - public boolean getUseOnlyServerErrorMessages() { - return this.useOnlyServerErrorMessages.getValueAsBoolean(); - } + public abstract boolean getUseOnlyServerErrorMessages(); /** * @return Returns the useReadAheadInput. */ - public boolean getUseReadAheadInput() { - return this.useReadAheadInput.getValueAsBoolean(); - } + public abstract boolean getUseReadAheadInput(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseServerPreparedStmts() { - return this.detectServerPreparedStmts.getValueAsBoolean(); - } + public abstract boolean getUseServerPreparedStmts(); /** * DOCUMENT ME! - * + * * @return Returns the useSqlStateCodes state. */ - public boolean getUseSqlStateCodes() { - return this.useSqlStateCodes.getValueAsBoolean(); - } + public abstract boolean getUseSqlStateCodes(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseSSL() { - return this.useSSL.getValueAsBoolean(); - } + public abstract boolean getUseSSL(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseStreamLengthsInPrepStmts() { - return this.useStreamLengthsInPrepStmts.getValueAsBoolean(); - } + public abstract boolean getUseStreamLengthsInPrepStmts(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseTimezone() { - return this.useTimezone.getValueAsBoolean(); - } + public abstract boolean getUseTimezone(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseUltraDevWorkAround() { - return this.useUltraDevWorkAround.getValueAsBoolean(); - } + public abstract boolean getUseUltraDevWorkAround(); /** * DOCUMENT ME! - * + * * @return Returns the useUnbufferedInput. */ - public boolean getUseUnbufferedInput() { - return this.useUnbufferedInput.getValueAsBoolean(); - } + public abstract boolean getUseUnbufferedInput(); /** * DOCUMENT ME! - * + * * @return */ - public boolean getUseUnicode() { - return this.useUnicodeAsBoolean; - } + public abstract boolean getUseUnicode(); /** * Returns whether or not the driver advises of proper usage. - * + * * @return the value of useUsageAdvisor */ - public boolean getUseUsageAdvisor() { - return this.useUsageAdvisorAsBoolean; - } + public abstract boolean getUseUsageAdvisor(); - public boolean getYearIsDateType() { - return this.yearIsDateType.getValueAsBoolean(); - } + public abstract boolean getYearIsDateType(); /** * @return Returns the zeroDateTimeBehavior. */ - public String getZeroDateTimeBehavior() { - return this.zeroDateTimeBehavior.getValueAsString(); - } + public abstract String getZeroDateTimeBehavior(); /** - * Initializes driver properties that come from a JNDI reference (in the - * case of a javax.sql.DataSource bound into some name service that doesn't - * handle Java objects directly). - * - * @param ref - * The JNDI Reference that holds RefAddrs for all properties - * @throws SQLException - * DOCUMENT ME! - */ - protected void initializeFromRef(Reference ref) throws SQLException { - int numPropertiesToSet = PROPERTY_LIST.size(); - - for (int i = 0; i < numPropertiesToSet; i++) { - java.lang.reflect.Field propertyField = (java.lang.reflect.Field) PROPERTY_LIST - .get(i); - - try { - ConnectionProperty propToSet = (ConnectionProperty) propertyField - .get(this); - - if (ref != null) { - propToSet.initializeFrom(ref); - } - } catch (IllegalAccessException iae) { - throw SQLError.createSQLException("Internal properties failure", - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - postInitialization(); - } - - /** - * Initializes driver properties that come from URL or properties passed to - * the driver manager. - * - * @param info - * DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - */ - protected void initializeProperties(Properties info) throws SQLException { - if (info != null) { - // For backwards-compatibility - String profileSqlLc = info.getProperty("profileSql"); - - if (profileSqlLc != null) { - info.put("profileSQL", profileSqlLc); - } - - Properties infoCopy = (Properties) info.clone(); - - infoCopy.remove(NonRegisteringDriver.HOST_PROPERTY_KEY); - infoCopy.remove(NonRegisteringDriver.USER_PROPERTY_KEY); - infoCopy.remove(NonRegisteringDriver.PASSWORD_PROPERTY_KEY); - infoCopy.remove(NonRegisteringDriver.DBNAME_PROPERTY_KEY); - infoCopy.remove(NonRegisteringDriver.PORT_PROPERTY_KEY); - infoCopy.remove("profileSql"); - - int numPropertiesToSet = PROPERTY_LIST.size(); - - for (int i = 0; i < numPropertiesToSet; i++) { - java.lang.reflect.Field propertyField = (java.lang.reflect.Field) PROPERTY_LIST - .get(i); - - try { - ConnectionProperty propToSet = (ConnectionProperty) propertyField - .get(this); - - propToSet.initializeFrom(infoCopy); - } catch (IllegalAccessException iae) { - throw SQLError.createSQLException( - "Unable to initialize driver properties due to " - + iae.toString(), - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - // TODO -- Not yet - /* - * int numUnknownProperties = infoCopy.size(); if - * (numUnknownProperties > 0) { StringBuffer errorMessageBuf = new - * StringBuffer( "Unknown connection "); - * errorMessageBuf.append((numUnknownProperties == 1) ? "property " : - * "properties "); Iterator propNamesItor = - * infoCopy.keySet().iterator(); errorMessageBuf.append("'"); - * errorMessageBuf.append(propNamesItor.next().toString()); - * errorMessageBuf.append("'"); while (propNamesItor.hasNext()) { - * errorMessageBuf.append(", '"); - * errorMessageBuf.append(propNamesItor.next().toString()); - * errorMessageBuf.append("'"); } throw new - * SQLException(errorMessageBuf.toString(), - * SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } - */ - postInitialization(); - } - } - - protected void postInitialization() throws SQLException { - - // Support 'old' profileSql capitalization - if (this.profileSql.getValueAsObject() != null) { - this.profileSQL.initializeFrom(this.profileSql.getValueAsObject() - .toString()); - } - - this.reconnectTxAtEndAsBoolean = ((Boolean) this.reconnectAtTxEnd - .getValueAsObject()).booleanValue(); - - // Adjust max rows - if (this.getMaxRows() == 0) { - // adjust so that it will become MysqlDefs.MAX_ROWS - // in execSQL() - this.maxRows.setValueAsObject(new Integer(-1)); - } - - // - // Check character encoding - // - String testEncoding = this.getEncoding(); - - if (testEncoding != null) { - // Attempt to use the encoding, and bail out if it - // can't be used - try { - String testString = "abc"; - testString.getBytes(testEncoding); - } catch (UnsupportedEncodingException UE) { - throw SQLError.createSQLException("Unsupported character " + "encoding '" - + testEncoding + "'.", "0S100"); - } - } - - // Metadata caching is only supported on JDK-1.4 and newer - // because it relies on LinkedHashMap being present. - // Check (and disable) if not supported - if (((Boolean) this.cacheResultSetMetadata.getValueAsObject()) - .booleanValue()) { - try { - Class.forName("java.util.LinkedHashMap"); - } catch (ClassNotFoundException cnfe) { - this.cacheResultSetMetadata.setValue(false); - } - } - - this.cacheResultSetMetaDataAsBoolean = this.cacheResultSetMetadata - .getValueAsBoolean(); - this.useUnicodeAsBoolean = this.useUnicode.getValueAsBoolean(); - this.characterEncodingAsString = ((String) this.characterEncoding - .getValueAsObject()); - this.highAvailabilityAsBoolean = this.autoReconnect.getValueAsBoolean(); - this.autoReconnectForPoolsAsBoolean = this.autoReconnectForPools - .getValueAsBoolean(); - this.maxRowsAsInt = ((Integer) this.maxRows.getValueAsObject()) - .intValue(); - this.profileSQLAsBoolean = this.profileSQL.getValueAsBoolean(); - this.useUsageAdvisorAsBoolean = this.useUsageAdvisor - .getValueAsBoolean(); - this.useOldUTF8BehaviorAsBoolean = this.useOldUTF8Behavior - .getValueAsBoolean(); - this.autoGenerateTestcaseScriptAsBoolean = this.autoGenerateTestcaseScript - .getValueAsBoolean(); - this.maintainTimeStatsAsBoolean = this.maintainTimeStats - .getValueAsBoolean(); - this.jdbcCompliantTruncationForReads = getJdbcCompliantTruncation(); - - if (getUseCursorFetch()) { - // assume they want to use server-side prepared statements - // because they're required for this functionality - setDetectServerPreparedStmts(true); - } - } - - /** * DOCUMENT ME! - * + * * @param property */ - public void setAllowLoadLocalInfile(boolean property) { - this.allowLoadLocalInfile.setValue(property); - } + public abstract void setAllowLoadLocalInfile(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setAllowMultiQueries(boolean property) { - this.allowMultiQueries.setValue(property); - } + public abstract void setAllowMultiQueries(boolean property); /** * @param allowNanAndInf * The allowNanAndInf to set. */ - public void setAllowNanAndInf(boolean flag) { - this.allowNanAndInf.setValue(flag); - } + public abstract void setAllowNanAndInf(boolean flag); /** * @param allowUrlInLocalInfile * The allowUrlInLocalInfile to set. */ - public void setAllowUrlInLocalInfile(boolean flag) { - this.allowUrlInLocalInfile.setValue(flag); - } + public abstract void setAllowUrlInLocalInfile(boolean flag); /** * @param alwaysSendSetIsolation * The alwaysSendSetIsolation to set. */ - public void setAlwaysSendSetIsolation(boolean flag) { - this.alwaysSendSetIsolation.setValue(flag); - } + public abstract void setAlwaysSendSetIsolation(boolean flag); /** * @param autoDeserialize * The autoDeserialize to set. */ - public void setAutoDeserialize(boolean flag) { - this.autoDeserialize.setValue(flag); - } + public abstract void setAutoDeserialize(boolean flag); - public void setAutoGenerateTestcaseScript(boolean flag) { - this.autoGenerateTestcaseScript.setValue(flag); - this.autoGenerateTestcaseScriptAsBoolean = this.autoGenerateTestcaseScript - .getValueAsBoolean(); - } + public abstract void setAutoGenerateTestcaseScript(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The autoReconnect to set. */ - public void setAutoReconnect(boolean flag) { - this.autoReconnect.setValue(flag); - } + public abstract void setAutoReconnect(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setAutoReconnectForConnectionPools(boolean property) { - this.autoReconnectForPools.setValue(property); - this.autoReconnectForPoolsAsBoolean = this.autoReconnectForPools - .getValueAsBoolean(); - } + public abstract void setAutoReconnectForConnectionPools(boolean property); /** * DOCUMENT ME! - * + * * @param flag * The autoReconnectForPools to set. */ - public void setAutoReconnectForPools(boolean flag) { - this.autoReconnectForPools.setValue(flag); - } + public abstract void setAutoReconnectForPools(boolean flag); /** * @param blobSendChunkSize * The blobSendChunkSize to set. */ - public void setBlobSendChunkSize(String value) throws SQLException { - this.blobSendChunkSize.setValue(value); - } + public abstract void setBlobSendChunkSize(String value) throws SQLException; /** * DOCUMENT ME! - * + * * @param flag * The cacheCallableStatements to set. */ - public void setCacheCallableStatements(boolean flag) { - this.cacheCallableStatements.setValue(flag); - } + public abstract void setCacheCallableStatements(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The cachePreparedStatements to set. */ - public void setCachePreparedStatements(boolean flag) { - this.cachePreparedStatements.setValue(flag); - } + public abstract void setCachePreparedStatements(boolean flag); /** * Sets whether or not we should cache result set metadata. - * + * * @param property */ - public void setCacheResultSetMetadata(boolean property) { - this.cacheResultSetMetadata.setValue(property); - this.cacheResultSetMetaDataAsBoolean = this.cacheResultSetMetadata - .getValueAsBoolean(); - } + public abstract void setCacheResultSetMetadata(boolean property); /** * @param cacheServerConfiguration * The cacheServerConfiguration to set. */ - public void setCacheServerConfiguration(boolean flag) { - this.cacheServerConfiguration.setValue(flag); - } + public abstract void setCacheServerConfiguration(boolean flag); /** * Configures the number of callable statements to cache. (this is * configurable during the life of the connection). - * + * * @param size * The callableStatementCacheSize to set. + * @throws SQLException */ - public void setCallableStatementCacheSize(int size) { - this.callableStatementCacheSize.setValue(size); - } + public abstract void setCallableStatementCacheSize(int size) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setCapitalizeDBMDTypes(boolean property) { - this.capitalizeTypeNames.setValue(property); - } + public abstract void setCapitalizeDBMDTypes(boolean property); /** * DOCUMENT ME! - * + * * @param flag * The capitalizeTypeNames to set. */ - public void setCapitalizeTypeNames(boolean flag) { - this.capitalizeTypeNames.setValue(flag); - } + public abstract void setCapitalizeTypeNames(boolean flag); /** * DOCUMENT ME! - * + * * @param encoding * The characterEncoding to set. */ - public void setCharacterEncoding(String encoding) { - this.characterEncoding.setValue(encoding); - } + public abstract void setCharacterEncoding(String encoding); /** * DOCUMENT ME! - * + * * @param characterSet * The characterSetResults to set. */ - public void setCharacterSetResults(String characterSet) { - this.characterSetResults.setValue(characterSet); - } + public abstract void setCharacterSetResults(String characterSet); /** * DOCUMENT ME! - * + * * @param flag * The clobberStreamingResults to set. */ - public void setClobberStreamingResults(boolean flag) { - this.clobberStreamingResults.setValue(flag); - } + public abstract void setClobberStreamingResults(boolean flag); - public void setClobCharacterEncoding(String encoding) { - this.clobCharacterEncoding.setValue(encoding); - } + public abstract void setClobCharacterEncoding(String encoding); /** * DOCUMENT ME! - * + * * @param collation * The connectionCollation to set. */ - public void setConnectionCollation(String collation) { - this.connectionCollation.setValue(collation); - } + public abstract void setConnectionCollation(String collation); /** * DOCUMENT ME! - * + * * @param timeoutMs + * @throws SQLException */ - public void setConnectTimeout(int timeoutMs) { - this.connectTimeout.setValue(timeoutMs); - } + public abstract void setConnectTimeout(int timeoutMs) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setContinueBatchOnError(boolean property) { - this.continueBatchOnError.setValue(property); - } + public abstract void setContinueBatchOnError(boolean property); - public void setCreateDatabaseIfNotExist(boolean flag) { - this.createDatabaseIfNotExist.setValue(flag); - } + public abstract void setCreateDatabaseIfNotExist(boolean flag); - public void setDefaultFetchSize(int n) { - this.defaultFetchSize.setValue(n); - } + public abstract void setDefaultFetchSize(int n) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setDetectServerPreparedStmts(boolean property) { - this.detectServerPreparedStmts.setValue(property); - } + public abstract void setDetectServerPreparedStmts(boolean property); /** * @param dontTrackOpenResources * The dontTrackOpenResources to set. */ - public void setDontTrackOpenResources(boolean flag) { - this.dontTrackOpenResources.setValue(flag); - } + public abstract void setDontTrackOpenResources(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The dumpQueriesOnException to set. */ - public void setDumpQueriesOnException(boolean flag) { - this.dumpQueriesOnException.setValue(flag); - } + public abstract void setDumpQueriesOnException(boolean flag); /** * @param dynamicCalendars * The dynamicCalendars to set. */ - public void setDynamicCalendars(boolean flag) { - this.dynamicCalendars.setValue(flag); - } + public abstract void setDynamicCalendars(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The elideSetAutoCommits to set. */ - public void setElideSetAutoCommits(boolean flag) { - this.elideSetAutoCommits.setValue(flag); - } + public abstract void setElideSetAutoCommits(boolean flag); - public void setEmptyStringsConvertToZero(boolean flag) { - this.emptyStringsConvertToZero.setValue(flag); - } + public abstract void setEmptyStringsConvertToZero(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setEmulateLocators(boolean property) { - this.emulateLocators.setValue(property); - } + public abstract void setEmulateLocators(boolean property); /** * @param emulateUnsupportedPstmts * The emulateUnsupportedPstmts to set. */ - public void setEmulateUnsupportedPstmts(boolean flag) { - this.emulateUnsupportedPstmts.setValue(flag); - } + public abstract void setEmulateUnsupportedPstmts(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The enablePacketDebug to set. */ - public void setEnablePacketDebug(boolean flag) { - this.enablePacketDebug.setValue(flag); - } + public abstract void setEnablePacketDebug(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setEncoding(String property) { - this.characterEncoding.setValue(property); - this.characterEncodingAsString = this.characterEncoding - .getValueAsString(); - } + public abstract void setEncoding(String property); /** * DOCUMENT ME! - * + * * @param flag * The explainSlowQueries to set. */ - public void setExplainSlowQueries(boolean flag) { - this.explainSlowQueries.setValue(flag); - } + public abstract void setExplainSlowQueries(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The failOverReadOnly to set. */ - public void setFailOverReadOnly(boolean flag) { - this.failOverReadOnly.setValue(flag); - } + public abstract void setFailOverReadOnly(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The gatherPerformanceMetrics to set. */ - public void setGatherPerformanceMetrics(boolean flag) { - this.gatherPerformanceMetrics.setValue(flag); - } + public abstract void setGatherPerformanceMetrics(boolean flag); /** - * DOCUMENT ME! - * - * @param property - */ - protected void setHighAvailability(boolean property) { - this.autoReconnect.setValue(property); - this.highAvailabilityAsBoolean = this.autoReconnect.getValueAsBoolean(); - } - - /** * @param holdResultsOpenOverStatementClose * The holdResultsOpenOverStatementClose to set. */ - public void setHoldResultsOpenOverStatementClose(boolean flag) { - this.holdResultsOpenOverStatementClose.setValue(flag); - } + public abstract void setHoldResultsOpenOverStatementClose(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setIgnoreNonTxTables(boolean property) { - this.ignoreNonTxTables.setValue(property); - } + public abstract void setIgnoreNonTxTables(boolean property); /** * DOCUMENT ME! - * + * * @param property + * @throws SQLException */ - public void setInitialTimeout(int property) { - this.initialTimeout.setValue(property); - } + public abstract void setInitialTimeout(int property) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setIsInteractiveClient(boolean property) { - this.isInteractiveClient.setValue(property); - } + public abstract void setIsInteractiveClient(boolean property); /** * DOCUMENT ME! - * + * * @param flag * The jdbcCompliantTruncation to set. */ - public void setJdbcCompliantTruncation(boolean flag) { - this.jdbcCompliantTruncation.setValue(flag); - } + public abstract void setJdbcCompliantTruncation(boolean flag); /** * @param locatorFetchBufferSize * The locatorFetchBufferSize to set. */ - public void setLocatorFetchBufferSize(String value) throws SQLException { - this.locatorFetchBufferSize.setValue(value); - } + public abstract void setLocatorFetchBufferSize(String value) + throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setLogger(String property) { - this.loggerClassName.setValueAsObject(property); - } + public abstract void setLogger(String property); /** * DOCUMENT ME! - * + * * @param className * The loggerClassName to set. */ - public void setLoggerClassName(String className) { - this.loggerClassName.setValue(className); - } + public abstract void setLoggerClassName(String className); /** * DOCUMENT ME! - * + * * @param flag * The logSlowQueries to set. */ - public void setLogSlowQueries(boolean flag) { - this.logSlowQueries.setValue(flag); - } + public abstract void setLogSlowQueries(boolean flag); - public void setMaintainTimeStats(boolean flag) { - this.maintainTimeStats.setValue(flag); - this.maintainTimeStatsAsBoolean = this.maintainTimeStats - .getValueAsBoolean(); - } + public abstract void setMaintainTimeStats(boolean flag); /** * DOCUMENT ME! - * + * * @param sizeInBytes * The maxQuerySizeToLog to set. + * @throws SQLException */ - public void setMaxQuerySizeToLog(int sizeInBytes) { - this.maxQuerySizeToLog.setValue(sizeInBytes); - } + public abstract void setMaxQuerySizeToLog(int sizeInBytes) throws SQLException; /** * DOCUMENT ME! - * + * * @param property + * @throws SQLException */ - public void setMaxReconnects(int property) { - this.maxReconnects.setValue(property); - } + public abstract void setMaxReconnects(int property) throws SQLException; /** * DOCUMENT ME! - * + * * @param property + * @throws SQLException */ - public void setMaxRows(int property) { - this.maxRows.setValue(property); - this.maxRowsAsInt = this.maxRows.getValueAsInt(); - } + public abstract void setMaxRows(int property) throws SQLException; /** * Sets the number of queries that metadata can be cached if caching is * enabled. - * + * * @param value * the number of queries to cache metadata for. + * @throws SQLException */ - public void setMetadataCacheSize(int value) { - this.metadataCacheSize.setValue(value); - } + public abstract void setMetadataCacheSize(int value) throws SQLException; /** * @param noDatetimeStringSync * The noDatetimeStringSync to set. */ - public void setNoDatetimeStringSync(boolean flag) { - this.noDatetimeStringSync.setValue(flag); - } + public abstract void setNoDatetimeStringSync(boolean flag); - public void setNullCatalogMeansCurrent(boolean value) { - this.nullCatalogMeansCurrent.setValue(value); - } + public abstract void setNullCatalogMeansCurrent(boolean value); - public void setNullNamePatternMatchesAll(boolean value) { - this.nullNamePatternMatchesAll.setValue(value); - } + public abstract void setNullNamePatternMatchesAll(boolean value); /** * DOCUMENT ME! - * + * * @param size * The packetDebugBufferSize to set. + * @throws SQLException */ - public void setPacketDebugBufferSize(int size) { - this.packetDebugBufferSize.setValue(size); - } + public abstract void setPacketDebugBufferSize(int size) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setParanoid(boolean property) { - this.paranoid.setValue(property); - } + public abstract void setParanoid(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setPedantic(boolean property) { - this.pedantic.setValue(property); - } + public abstract void setPedantic(boolean property); /** * DOCUMENT ME! - * + * * @param cacheSize * The preparedStatementCacheSize to set. + * @throws SQLException */ - public void setPreparedStatementCacheSize(int cacheSize) { - this.preparedStatementCacheSize.setValue(cacheSize); - } + public abstract void setPreparedStatementCacheSize(int cacheSize) throws SQLException; /** * DOCUMENT ME! - * + * * @param cacheSqlLimit * The preparedStatementCacheSqlLimit to set. + * @throws SQLException */ - public void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) { - this.preparedStatementCacheSqlLimit.setValue(cacheSqlLimit); - } + public abstract void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setProfileSql(boolean property) { - this.profileSQL.setValue(property); - this.profileSQLAsBoolean = this.profileSQL.getValueAsBoolean(); - } + public abstract void setProfileSql(boolean property); /** * DOCUMENT ME! - * + * * @param flag * The profileSQL to set. */ - public void setProfileSQL(boolean flag) { - this.profileSQL.setValue(flag); - } + public abstract void setProfileSQL(boolean flag); /** * @param propertiesTransform * The propertiesTransform to set. */ - public void setPropertiesTransform(String value) { - this.propertiesTransform.setValue(value); - } + public abstract void setPropertiesTransform(String value); /** * DOCUMENT ME! - * + * * @param property + * @throws SQLException */ - public void setQueriesBeforeRetryMaster(int property) { - this.queriesBeforeRetryMaster.setValue(property); - } + public abstract void setQueriesBeforeRetryMaster(int property) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setReconnectAtTxEnd(boolean property) { - this.reconnectAtTxEnd.setValue(property); - this.reconnectTxAtEndAsBoolean = this.reconnectAtTxEnd - .getValueAsBoolean(); - } + public abstract void setReconnectAtTxEnd(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setRelaxAutoCommit(boolean property) { - this.relaxAutoCommit.setValue(property); - } + public abstract void setRelaxAutoCommit(boolean property); /** * DOCUMENT ME! - * + * * @param millis * The reportMetricsIntervalMillis to set. + * @throws SQLException */ - public void setReportMetricsIntervalMillis(int millis) { - this.reportMetricsIntervalMillis.setValue(millis); - } + public abstract void setReportMetricsIntervalMillis(int millis) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setRequireSSL(boolean property) { - this.requireSSL.setValue(property); - } + public abstract void setRequireSSL(boolean property); - public void setRetainStatementAfterResultSetClose(boolean flag) { - this.retainStatementAfterResultSetClose.setValue(flag); - } + public abstract void setRetainStatementAfterResultSetClose(boolean flag); /** * @param rollbackOnPooledClose * The rollbackOnPooledClose to set. */ - public void setRollbackOnPooledClose(boolean flag) { - this.rollbackOnPooledClose.setValue(flag); - } + public abstract void setRollbackOnPooledClose(boolean flag); /** * Sets whether or not hosts will be picked in a round-robin fashion. - * + * * @param flag * The roundRobinLoadBalance property to set. */ - public void setRoundRobinLoadBalance(boolean flag) { - this.roundRobinLoadBalance.setValue(flag); - } + public abstract void setRoundRobinLoadBalance(boolean flag); /** * @param runningCTS13 * The runningCTS13 to set. */ - public void setRunningCTS13(boolean flag) { - this.runningCTS13.setValue(flag); - } + public abstract void setRunningCTS13(boolean flag); /** * DOCUMENT ME! - * + * * @param property + * @throws SQLException */ - public void setSecondsBeforeRetryMaster(int property) { - this.secondsBeforeRetryMaster.setValue(property); - } + public abstract void setSecondsBeforeRetryMaster(int property) throws SQLException; /** * DOCUMENT ME! - * + * * @param property * DOCUMENT ME! */ - public void setServerTimezone(String property) { - this.serverTimezone.setValue(property); - } + public abstract void setServerTimezone(String property); /** * @param sessionVariables * The sessionVariables to set. */ - public void setSessionVariables(String variables) { - this.sessionVariables.setValue(variables); - } + public abstract void setSessionVariables(String variables); /** * DOCUMENT ME! - * + * * @param millis * The slowQueryThresholdMillis to set. + * @throws SQLException */ - public void setSlowQueryThresholdMillis(int millis) { - this.slowQueryThresholdMillis.setValue(millis); - } + public abstract void setSlowQueryThresholdMillis(int millis) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setSocketFactoryClassName(String property) { - this.socketFactoryClassName.setValue(property); - } + public abstract void setSocketFactoryClassName(String property); /** * DOCUMENT ME! - * + * * @param property + * @throws SQLException */ - public void setSocketTimeout(int property) { - this.socketTimeout.setValue(property); - } + public abstract void setSocketTimeout(int property) throws SQLException; /** * DOCUMENT ME! - * + * * @param property */ - public void setStrictFloatingPoint(boolean property) { - this.strictFloatingPoint.setValue(property); - } + public abstract void setStrictFloatingPoint(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setStrictUpdates(boolean property) { - this.strictUpdates.setValue(property); - } + public abstract void setStrictUpdates(boolean property); /** * @param tinyInt1isBit * The tinyInt1isBit to set. */ - public void setTinyInt1isBit(boolean flag) { - this.tinyInt1isBit.setValue(flag); - } + public abstract void setTinyInt1isBit(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The logProtocol to set. */ - public void setTraceProtocol(boolean flag) { - this.traceProtocol.setValue(flag); - } + public abstract void setTraceProtocol(boolean flag); - public void setTransformedBitIsBoolean(boolean flag) { - this.transformedBitIsBoolean.setValue(flag); - } + public abstract void setTransformedBitIsBoolean(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setUseCompression(boolean property) { - this.useCompression.setValue(property); - } + public abstract void setUseCompression(boolean property); /** * @param useFastIntParsing * The useFastIntParsing to set. */ - public void setUseFastIntParsing(boolean flag) { - this.useFastIntParsing.setValue(flag); - } + public abstract void setUseFastIntParsing(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setUseHostsInPrivileges(boolean property) { - this.useHostsInPrivileges.setValue(property); - } + public abstract void setUseHostsInPrivileges(boolean property); - public void setUseInformationSchema(boolean flag) { - this.useInformationSchema.setValue(flag); - } + public abstract void setUseInformationSchema(boolean flag); /** * @param useLocalSessionState * The useLocalSessionState to set. */ - public void setUseLocalSessionState(boolean flag) { - this.useLocalSessionState.setValue(flag); - } + public abstract void setUseLocalSessionState(boolean flag); /** * @param useOldUTF8Behavior * The useOldUTF8Behavior to set. */ - public void setUseOldUTF8Behavior(boolean flag) { - this.useOldUTF8Behavior.setValue(flag); - this.useOldUTF8BehaviorAsBoolean = this.useOldUTF8Behavior - .getValueAsBoolean(); - } + public abstract void setUseOldUTF8Behavior(boolean flag); /** * @param useOnlyServerErrorMessages * The useOnlyServerErrorMessages to set. */ - public void setUseOnlyServerErrorMessages(boolean flag) { - this.useOnlyServerErrorMessages.setValue(flag); - } + public abstract void setUseOnlyServerErrorMessages(boolean flag); /** * @param useReadAheadInput * The useReadAheadInput to set. */ - public void setUseReadAheadInput(boolean flag) { - this.useReadAheadInput.setValue(flag); - } + public abstract void setUseReadAheadInput(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The detectServerPreparedStmts to set. */ - public void setUseServerPreparedStmts(boolean flag) { - this.detectServerPreparedStmts.setValue(flag); - } + public abstract void setUseServerPreparedStmts(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The useSqlStateCodes to set. */ - public void setUseSqlStateCodes(boolean flag) { - this.useSqlStateCodes.setValue(flag); - } + public abstract void setUseSqlStateCodes(boolean flag); /** * DOCUMENT ME! - * + * * @param property */ - public void setUseSSL(boolean property) { - this.useSSL.setValue(property); - } + public abstract void setUseSSL(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setUseStreamLengthsInPrepStmts(boolean property) { - this.useStreamLengthsInPrepStmts.setValue(property); - } + public abstract void setUseStreamLengthsInPrepStmts(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setUseTimezone(boolean property) { - this.useTimezone.setValue(property); - } + public abstract void setUseTimezone(boolean property); /** * DOCUMENT ME! - * + * * @param property */ - public void setUseUltraDevWorkAround(boolean property) { - this.useUltraDevWorkAround.setValue(property); - } + public abstract void setUseUltraDevWorkAround(boolean property); /** * DOCUMENT ME! - * + * * @param flag * The useUnbufferedInput to set. */ - public void setUseUnbufferedInput(boolean flag) { - this.useUnbufferedInput.setValue(flag); - } + public abstract void setUseUnbufferedInput(boolean flag); /** * DOCUMENT ME! - * + * * @param flag * The useUnicode to set. */ - public void setUseUnicode(boolean flag) { - this.useUnicode.setValue(flag); - this.useUnicodeAsBoolean = this.useUnicode.getValueAsBoolean(); - } + public abstract void setUseUnicode(boolean flag); /** * Sets whether or not the driver advises of proper usage. - * + * * @param useUsageAdvisorFlag * whether or not the driver advises of proper usage. */ - public void setUseUsageAdvisor(boolean useUsageAdvisorFlag) { - this.useUsageAdvisor.setValue(useUsageAdvisorFlag); - this.useUsageAdvisorAsBoolean = this.useUsageAdvisor - .getValueAsBoolean(); - } + public abstract void setUseUsageAdvisor(boolean useUsageAdvisorFlag); - public void setYearIsDateType(boolean flag) { - this.yearIsDateType.setValue(flag); - } + public abstract void setYearIsDateType(boolean flag); /** * @param zeroDateTimeBehavior * The zeroDateTimeBehavior to set. */ - public void setZeroDateTimeBehavior(String behavior) { - this.zeroDateTimeBehavior.setValue(behavior); - } + public abstract void setZeroDateTimeBehavior(String behavior); - protected void storeToRef(Reference ref) throws SQLException { - int numPropertiesToSet = PROPERTY_LIST.size(); - - for (int i = 0; i < numPropertiesToSet; i++) { - java.lang.reflect.Field propertyField = (java.lang.reflect.Field) PROPERTY_LIST - .get(i); - - try { - ConnectionProperty propToStore = (ConnectionProperty) propertyField - .get(this); - - if (ref != null) { - propToStore.storeTo(ref); - } - } catch (IllegalAccessException iae) { - throw SQLError.createSQLException("Huh?"); - } - } - } - /** * DOCUMENT ME! - * + * * @return Returns the useUnbufferedInput. */ - public boolean useUnbufferedInput() { - return this.useUnbufferedInput.getValueAsBoolean(); - } + public abstract boolean useUnbufferedInput(); - public boolean getUseCursorFetch() { - return this.useCursorFetch.getValueAsBoolean(); - } + public abstract boolean getUseCursorFetch(); - public void setUseCursorFetch(boolean flag) { - this.useCursorFetch.setValue(flag); - } + public abstract void setUseCursorFetch(boolean flag); - public boolean getOverrideSupportsIntegrityEnhancementFacility() { - return this.overrideSupportsIntegrityEnhancementFacility.getValueAsBoolean(); - } + public abstract boolean getOverrideSupportsIntegrityEnhancementFacility(); - public void setOverrideSupportsIntegrityEnhancementFacility(boolean flag) { - this.overrideSupportsIntegrityEnhancementFacility.setValue(flag); - } + public abstract void setOverrideSupportsIntegrityEnhancementFacility( + boolean flag); - public boolean getNoTimezoneConversionForTimeType() { - return this.noTimezoneConversionForTimeType.getValueAsBoolean(); - } + public abstract boolean getNoTimezoneConversionForTimeType(); - public void setNoTimezoneConversionForTimeType(boolean flag) { - this.noTimezoneConversionForTimeType.setValue(flag); - } + public abstract void setNoTimezoneConversionForTimeType(boolean flag); - public boolean getUseJDBCCompliantTimezoneShift() { - return this.useJDBCCompliantTimezoneShift.getValueAsBoolean(); - } + public abstract boolean getUseJDBCCompliantTimezoneShift(); - public void setUseJDBCCompliantTimezoneShift(boolean flag) { - this.useJDBCCompliantTimezoneShift.setValue(flag); - } + public abstract void setUseJDBCCompliantTimezoneShift(boolean flag); - public boolean getAutoClosePStmtStreams() { - return this.autoClosePStmtStreams.getValueAsBoolean(); - } + public abstract boolean getAutoClosePStmtStreams(); - public void setAutoClosePStmtStreams(boolean flag) { - this.autoClosePStmtStreams.setValue(flag); - } + public abstract void setAutoClosePStmtStreams(boolean flag); - public boolean getProcessEscapeCodesForPrepStmts() { - return this.processEscapeCodesForPrepStmts.getValueAsBoolean(); - } + public abstract boolean getProcessEscapeCodesForPrepStmts(); - public void setProcessEscapeCodesForPrepStmts(boolean flag) { - this.processEscapeCodesForPrepStmts.setValue(flag); - } + public abstract void setProcessEscapeCodesForPrepStmts(boolean flag); - public boolean getUseGmtMillisForDatetimes() { - return this.useGmtMillisForDatetimes.getValueAsBoolean(); - } + public abstract boolean getUseGmtMillisForDatetimes(); - public void setUseGmtMillisForDatetimes(boolean flag) { - this.useGmtMillisForDatetimes.setValue(flag); - } + public abstract void setUseGmtMillisForDatetimes(boolean flag); - public boolean getDumpMetadataOnColumnNotFound() { - return this.dumpMetadataOnColumnNotFound.getValueAsBoolean(); - } + public abstract boolean getDumpMetadataOnColumnNotFound(); - public void setDumpMetadataOnColumnNotFound(boolean flag) { - this.dumpMetadataOnColumnNotFound.setValue(flag); - } + public abstract void setDumpMetadataOnColumnNotFound(boolean flag); - public String getResourceId() { - return this.resourceId.getValueAsString(); - } + public abstract String getResourceId(); - public void setResourceId(String resourceId) { - this.resourceId.setValue(resourceId); - } + public abstract void setResourceId(String resourceId); - public boolean getRewriteBatchedStatements() { - return this.rewriteBatchedStatements.getValueAsBoolean(); - } + public abstract boolean getRewriteBatchedStatements(); - public void setRewriteBatchedStatements(boolean flag) { - this.rewriteBatchedStatements.setValue(flag); - } + public abstract void setRewriteBatchedStatements(boolean flag); - public boolean getJdbcCompliantTruncationForReads() { - return this.jdbcCompliantTruncationForReads; - } + public abstract boolean getJdbcCompliantTruncationForReads(); - public void setJdbcCompliantTruncationForReads( - boolean jdbcCompliantTruncationForReads) { - this.jdbcCompliantTruncationForReads = jdbcCompliantTruncationForReads; - } + public abstract void setJdbcCompliantTruncationForReads( + boolean jdbcCompliantTruncationForReads); - public boolean getUseJvmCharsetConverters() { - return this.useJvmCharsetConverters.getValueAsBoolean(); - } + public abstract boolean getUseJvmCharsetConverters(); - public void setUseJvmCharsetConverters(boolean flag) { - this.useJvmCharsetConverters.setValue(flag); - } + public abstract void setUseJvmCharsetConverters(boolean flag); - public boolean getPinGlobalTxToPhysicalConnection() { - return this.pinGlobalTxToPhysicalConnection.getValueAsBoolean(); - } + public abstract boolean getPinGlobalTxToPhysicalConnection(); - public void setPinGlobalTxToPhysicalConnection(boolean flag) { - this.pinGlobalTxToPhysicalConnection.setValue(flag); - } + public abstract void setPinGlobalTxToPhysicalConnection(boolean flag); - /* - * "Aliases" which match the property names to make using - * from datasources easier. - */ + public abstract void setGatherPerfMetrics(boolean flag); - public void setGatherPerfMetrics(boolean flag) { - setGatherPerformanceMetrics(flag); - } + public abstract boolean getGatherPerfMetrics(); - public boolean getGatherPerfMetrics() { - return getGatherPerformanceMetrics(); - } + public abstract void setUltraDevHack(boolean flag); - public void setUltraDevHack(boolean flag) { - setUseUltraDevWorkAround(flag); - } + public abstract boolean getUltraDevHack(); - public boolean getUltraDevHack() { - return getUseUltraDevWorkAround(); - } + public abstract void setInteractiveClient(boolean property); - public void setInteractiveClient(boolean property) { - setIsInteractiveClient(property); - } + public abstract void setSocketFactory(String name); - public void setSocketFactory(String name) { - setSocketFactoryClassName(name); - } + public abstract String getSocketFactory(); - public String getSocketFactory() { - return getSocketFactoryClassName(); - } + public abstract void setUseServerPrepStmts(boolean flag); - public void setUseServerPrepStmts(boolean flag) { - setUseServerPreparedStmts(flag); - } + public abstract boolean getUseServerPrepStmts(); - public boolean getUseServerPrepStmts() { - return getUseServerPreparedStmts(); - } + public abstract void setCacheCallableStmts(boolean flag); - public void setCacheCallableStmts(boolean flag) { - setCacheCallableStatements(flag); - } + public abstract boolean getCacheCallableStmts(); - public boolean getCacheCallableStmts() { - return getCacheCallableStatements(); - } + public abstract void setCachePrepStmts(boolean flag); - public void setCachePrepStmts(boolean flag) { - setCachePreparedStatements(flag); - } + public abstract boolean getCachePrepStmts(); - public boolean getCachePrepStmts() { - return getCachePreparedStatements(); - } + public abstract void setCallableStmtCacheSize(int cacheSize) throws SQLException; - public void setCallableStmtCacheSize(int cacheSize) { - setCallableStatementCacheSize(cacheSize); - } + public abstract int getCallableStmtCacheSize(); - public int getCallableStmtCacheSize() { - return getCallableStatementCacheSize(); - } + public abstract void setPrepStmtCacheSize(int cacheSize) throws SQLException; - public void setPrepStmtCacheSize(int cacheSize) { - setPreparedStatementCacheSize(cacheSize); - } + public abstract int getPrepStmtCacheSize(); - public int getPrepStmtCacheSize() { - return getPreparedStatementCacheSize(); - } + public abstract void setPrepStmtCacheSqlLimit(int sqlLimit) throws SQLException; - public void setPrepStmtCacheSqlLimit(int sqlLimit) { - setPreparedStatementCacheSqlLimit(sqlLimit); - } + public abstract int getPrepStmtCacheSqlLimit(); - public int getPrepStmtCacheSqlLimit() { - return getPreparedStatementCacheSqlLimit(); - } + public abstract boolean getNoAccessToProcedureBodies(); - public boolean getNoAccessToProcedureBodies() { - return this.noAccessToProcedureBodies.getValueAsBoolean(); - } + public abstract void setNoAccessToProcedureBodies(boolean flag); - public void setNoAccessToProcedureBodies(boolean flag) { - this.noAccessToProcedureBodies.setValue(flag); - } + public abstract boolean getUseOldAliasMetadataBehavior(); - public boolean getUseOldAliasMetadataBehavior() { - return this.useOldAliasMetadataBehavior.getValueAsBoolean(); - } + public abstract void setUseOldAliasMetadataBehavior(boolean flag); - public void setUseOldAliasMetadataBehavior(boolean flag) { - this.useOldAliasMetadataBehavior.setValue(flag); - } + public abstract String getClientCertificateKeyStorePassword(); - public boolean getUseSSPSCompatibleTimezoneShift() { - return this.useSSPSCompatibleTimezoneShift.getValueAsBoolean(); - } + public abstract void setClientCertificateKeyStorePassword(String value); - public void setUseSSPSCompatibleTimezoneShift(boolean flag) { - this.useSSPSCompatibleTimezoneShift.setValue(flag); - } + public abstract String getClientCertificateKeyStoreType(); - public boolean getTreatUtilDateAsTimestamp() { - return this.treatUtilDateAsTimestamp.getValueAsBoolean(); - } + public abstract void setClientCertificateKeyStoreType(String value); - public void setTreatUtilDateAsTimestamp(boolean flag) { - this.treatUtilDateAsTimestamp.setValue(flag); - } + public abstract String getClientCertificateKeyStoreUrl(); - public boolean getUseFastDateParsing() { - return this.useFastDateParsing.getValueAsBoolean(); - } + public abstract void setClientCertificateKeyStoreUrl(String value); - public void setUseFastDateParsing(boolean flag) { - this.useFastDateParsing.setValue(flag); - } + public abstract String getTrustCertificateKeyStorePassword(); - public String getLocalSocketAddress() { - return this.localSocketAddress.getValueAsString(); - } + public abstract void setTrustCertificateKeyStorePassword(String value); - public void setLocalSocketAddress(String address) { - this.localSocketAddress.setValue(address); - } + public abstract String getTrustCertificateKeyStoreType(); - public void setUseConfigs(String configs) { - this.useConfigs.setValue(configs); - } + public abstract void setTrustCertificateKeyStoreType(String value); - public String getUseConfigs() { - return this.useConfigs.getValueAsString(); - } + public abstract String getTrustCertificateKeyStoreUrl(); - public boolean getGenerateSimpleParameterMetadata() { - return this.generateSimpleParameterMetadata.getValueAsBoolean(); - } + public abstract void setTrustCertificateKeyStoreUrl(String value); - public void setGenerateSimpleParameterMetadata(boolean flag) { - this.generateSimpleParameterMetadata.setValue(flag); - } + public abstract boolean getUseSSPSCompatibleTimezoneShift(); - public boolean getLogXaCommands() { - return this.logXaCommands.getValueAsBoolean(); - } + public abstract void setUseSSPSCompatibleTimezoneShift(boolean flag); - public void setLogXaCommands(boolean flag) { - this.logXaCommands.setValue(flag); - } + public abstract boolean getTreatUtilDateAsTimestamp(); - public int getResultSetSizeThreshold() { - return this.resultSetSizeThreshold.getValueAsInt(); - } + public abstract void setTreatUtilDateAsTimestamp(boolean flag); - public void setResultSetSizeThreshold(int threshold) { - this.resultSetSizeThreshold.setValue(threshold); - } + public abstract boolean getUseFastDateParsing(); - public boolean getEnableQueryTimeouts() { - return this.enableQueryTimeouts.getValueAsBoolean(); - } + public abstract void setUseFastDateParsing(boolean flag); - public void setEnableQueryTimeouts(boolean flag) { - this.enableQueryTimeouts.setValue(flag); - } + public abstract String getLocalSocketAddress(); - public boolean getPadCharsWithSpace() { - return this.padCharsWithSpace.getValueAsBoolean(); - } + public abstract void setLocalSocketAddress(String address); - public void setPadCharsWithSpace(boolean flag) { - this.padCharsWithSpace.setValue(flag); - } + public abstract void setUseConfigs(String configs); - public boolean getUseDynamicCharsetInfo() { - return this.useDynamicCharsetInfo.getValueAsBoolean(); - } + public abstract String getUseConfigs(); - public void setUseDynamicCharsetInfo(boolean flag) { - this.useDynamicCharsetInfo.setValue(flag); - } + public abstract boolean getGenerateSimpleParameterMetadata(); - public boolean getPopulateInsertRowWithDefaultValues() { - return this.populateInsertRowWithDefaultValues.getValueAsBoolean(); - } + public abstract void setGenerateSimpleParameterMetadata(boolean flag); - public void setPopulateInsertRowWithDefaultValues(boolean flag) { - this.populateInsertRowWithDefaultValues.setValue(flag); - } + public abstract boolean getLogXaCommands(); - public String getLoadBalanceStrategy() { - return this.loadBalanceStrategy.getValueAsString(); - } + public abstract void setLogXaCommands(boolean flag); - public void setLoadBalanceStrategy(String strategy) { - this.loadBalanceStrategy.setValue(strategy); - } + public abstract int getResultSetSizeThreshold(); - public boolean getUseNanosForElapsedTime() { - return this.useNanosForElapsedTime.getValueAsBoolean(); - } + public abstract void setResultSetSizeThreshold(int threshold) throws SQLException; - public void setUseNanosForElapsedTime(boolean flag) { - this.useNanosForElapsedTime.setValue(flag); - } + public abstract int getNetTimeoutForStreamingResults(); - public long getSlowQueryThresholdNanos() { - return this.slowQueryThresholdNanos.getValueAsLong(); - } + public abstract void setNetTimeoutForStreamingResults(int value) throws SQLException; - public void setSlowQueryThresholdNanos(long nanos) { - this.slowQueryThresholdNanos.setValue(nanos); - } + public abstract boolean getEnableQueryTimeouts(); - public boolean getTcpNoDelay() { - return this.tcpNoDelay.getValueAsBoolean(); - } + public abstract void setEnableQueryTimeouts(boolean flag); - public void setTcpNoDelay(boolean flag) { - this.tcpNoDelay.setValue(flag); - } + public abstract boolean getPadCharsWithSpace(); - public boolean getTcpKeepAlive() { - return this.tcpKeepAlive.getValueAsBoolean(); - } + public abstract void setPadCharsWithSpace(boolean flag); - public void setTcpKeepAlive(boolean flag) { - this.tcpKeepAlive.setValue(flag); - } + public abstract boolean getUseDynamicCharsetInfo(); - public int getTcpRcvBuf() { - return this.tcpRcvBuf.getValueAsInt(); - } + public abstract void setUseDynamicCharsetInfo(boolean flag); - public void setTcpRcvBuf(int bufSize) { - this.tcpRcvBuf.setValue(bufSize); - } + public abstract String getClientInfoProvider(); - public int getTcpSndBuf() { - return this.tcpSndBuf.getValueAsInt(); - } + public abstract void setClientInfoProvider(String classname); + + public abstract boolean getPopulateInsertRowWithDefaultValues(); - public void setTcpSndBuf(int bufSize) { - this.tcpSndBuf.setValue(bufSize); - } + public abstract void setPopulateInsertRowWithDefaultValues(boolean flag); + + public abstract String getLoadBalanceStrategy(); - public int getTcpTrafficClass() { - return this.tcpTrafficClass.getValueAsInt(); - } + public abstract void setLoadBalanceStrategy(String strategy); + + public abstract boolean getTcpNoDelay(); - public void setTcpTrafficClass(int classFlags) { - this.tcpTrafficClass.setValue(classFlags); - } + public abstract void setTcpNoDelay(boolean flag); - public boolean getIncludeInnodbStatusInDeadlockExceptions() { - return this.includeInnodbStatusInDeadlockExceptions.getValueAsBoolean(); - } + public abstract boolean getTcpKeepAlive(); - public void setIncludeInnodbStatusInDeadlockExceptions(boolean flag) { - this.includeInnodbStatusInDeadlockExceptions.setValue(flag); - } + public abstract void setTcpKeepAlive(boolean flag); - public boolean getBlobsAreStrings() { - return this.blobsAreStrings.getValueAsBoolean(); - } + public abstract int getTcpRcvBuf(); - public void setBlobsAreStrings(boolean flag) { - this.blobsAreStrings.setValue(flag); - } + public abstract void setTcpRcvBuf(int bufSize) throws SQLException; - public boolean getFunctionsNeverReturnBlobs() { - return this.functionsNeverReturnBlobs.getValueAsBoolean(); - } + public abstract int getTcpSndBuf(); + + public abstract void setTcpSndBuf(int bufSize) throws SQLException; - public void setFunctionsNeverReturnBlobs(boolean flag) { - this.functionsNeverReturnBlobs.setValue(flag); - } + public abstract int getTcpTrafficClass(); + + public abstract void setTcpTrafficClass(int classFlags) throws SQLException; + + public abstract boolean getUseNanosForElapsedTime(); + + public abstract void setUseNanosForElapsedTime(boolean flag); + + public abstract long getSlowQueryThresholdNanos(); + + public abstract void setSlowQueryThresholdNanos(long nanos) throws SQLException; + + public abstract String getStatementInterceptors(); + + public abstract void setStatementInterceptors(String value); + + public abstract boolean getUseDirectRowUnpack(); + + public abstract void setUseDirectRowUnpack(boolean flag); + + public abstract String getLargeRowSizeThreshold(); + + public abstract void setLargeRowSizeThreshold(String value) throws SQLException; + + public abstract boolean getUseBlobToStoreUTF8OutsideBMP(); + + public abstract void setUseBlobToStoreUTF8OutsideBMP(boolean flag); + + public abstract String getUtf8OutsideBmpExcludedColumnNamePattern(); + + public abstract void setUtf8OutsideBmpExcludedColumnNamePattern(String regexPattern); + + public abstract String getUtf8OutsideBmpIncludedColumnNamePattern(); + + public abstract void setUtf8OutsideBmpIncludedColumnNamePattern(String regexPattern); + + public abstract boolean getIncludeInnodbStatusInDeadlockExceptions(); + + public abstract void setIncludeInnodbStatusInDeadlockExceptions(boolean flag); + + public abstract boolean getIncludeThreadDumpInDeadlockExceptions(); + + public abstract void setIncludeThreadDumpInDeadlockExceptions(boolean flag); + + public abstract boolean getIncludeThreadNamesAsStatementComment(); + + public abstract void setIncludeThreadNamesAsStatementComment(boolean flag); + + public abstract boolean getBlobsAreStrings(); + + public abstract void setBlobsAreStrings(boolean flag); + + public abstract boolean getFunctionsNeverReturnBlobs(); + + public abstract void setFunctionsNeverReturnBlobs(boolean flag); + + public abstract boolean getAutoSlowLog(); + + public abstract void setAutoSlowLog(boolean flag); + + public abstract String getConnectionLifecycleInterceptors(); + + public abstract void setConnectionLifecycleInterceptors(String interceptors); + + public abstract String getProfilerEventHandler(); + + public abstract void setProfilerEventHandler(String handler); + + public boolean getVerifyServerCertificate(); + + public abstract void setVerifyServerCertificate(boolean flag); + + public abstract boolean getUseLegacyDatetimeCode(); + + public abstract void setUseLegacyDatetimeCode(boolean flag); + + public abstract int getSelfDestructOnPingSecondsLifetime(); + + public abstract void setSelfDestructOnPingSecondsLifetime(int seconds) throws SQLException; + + public abstract int getSelfDestructOnPingMaxOperations(); + + public abstract void setSelfDestructOnPingMaxOperations(int maxOperations) throws SQLException; + + public abstract boolean getUseColumnNamesInFindColumn(); + + public abstract void setUseColumnNamesInFindColumn(boolean flag); + + public abstract boolean getUseLocalTransactionState(); + + public abstract void setUseLocalTransactionState(boolean flag); + + public abstract boolean getCompensateOnDuplicateKeyUpdateCounts(); + + public abstract void setCompensateOnDuplicateKeyUpdateCounts(boolean flag); + + public abstract void setUseAffectedRows(boolean flag); + + public abstract boolean getUseAffectedRows(); + + public abstract void setPasswordCharacterEncoding(String characterSet); + + public abstract String getPasswordCharacterEncoding(); + + public abstract int getLoadBalanceBlacklistTimeout(); + + public abstract void setLoadBalanceBlacklistTimeout(int loadBalanceBlacklistTimeout) throws SQLException; + + public abstract void setRetriesAllDown(int retriesAllDown) throws SQLException; + + public abstract int getRetriesAllDown(); + + public ExceptionInterceptor getExceptionInterceptor(); + + public abstract void setExceptionInterceptors(String exceptionInterceptors); + + public abstract String getExceptionInterceptors(); + + + public abstract boolean getQueryTimeoutKillsConnection(); + + public abstract void setQueryTimeoutKillsConnection(boolean queryTimeoutKillsConnection); + + public int getMaxAllowedPacket(); + + boolean getRetainStatementAfterResultSetClose(); + + public abstract int getLoadBalancePingTimeout(); + + public abstract void setLoadBalancePingTimeout(int loadBalancePingTimeout) throws SQLException; + + public abstract boolean getLoadBalanceValidateConnectionOnSwapServer(); + + public abstract void setLoadBalanceValidateConnectionOnSwapServer(boolean loadBalanceValidateConnectionOnSwapServer); + + public abstract String getLoadBalanceConnectionGroup(); + + public abstract void setLoadBalanceConnectionGroup(String loadBalanceConnectionGroup); + + public abstract String getLoadBalanceExceptionChecker(); + + public abstract void setLoadBalanceExceptionChecker(String loadBalanceExceptionChecker); + + public abstract String getLoadBalanceSQLStateFailover(); + + public abstract void setLoadBalanceSQLStateFailover(String loadBalanceSQLStateFailover); + + public abstract String getLoadBalanceSQLExceptionSubclassFailover(); + + public abstract void setLoadBalanceSQLExceptionSubclassFailover(String loadBalanceSQLExceptionSubclassFailover); + + public abstract boolean getLoadBalanceEnableJMX(); + + public abstract void setLoadBalanceEnableJMX(boolean loadBalanceEnableJMX); + + public void setLoadBalanceAutoCommitStatementThreshold(int loadBalanceAutoCommitStatementThreshold) throws SQLException; + + public int getLoadBalanceAutoCommitStatementThreshold(); + + public void setLoadBalanceAutoCommitStatementRegex(String loadBalanceAutoCommitStatementRegex); + + public String getLoadBalanceAutoCommitStatementRegex(); + + public abstract void setAuthenticationPlugins(String authenticationPlugins); + + public abstract String getAuthenticationPlugins(); + + public abstract void setDisabledAuthenticationPlugins(String disabledAuthenticationPlugins); + + public abstract String getDisabledAuthenticationPlugins(); + + public abstract void setDefaultAuthenticationPlugin(String defaultAuthenticationPlugin); + + public abstract String getDefaultAuthenticationPlugin(); + + public abstract void setParseInfoCacheFactory(String factoryClassname); + + public abstract String getParseInfoCacheFactory(); + + public abstract void setServerConfigCacheFactory(String factoryClassname); + + public abstract String getServerConfigCacheFactory(); + + public abstract void setDisconnectOnExpiredPasswords(boolean disconnectOnExpiredPasswords); + + public abstract boolean getDisconnectOnExpiredPasswords(); + + public abstract boolean getAllowMasterDownConnections(); + + public abstract void setAllowMasterDownConnections(boolean connectIfMasterDown); + + public abstract boolean getReplicationEnableJMX(); + + public abstract void setReplicationEnableJMX(boolean replicationEnableJMX); + + public abstract void setGetProceduresReturnsFunctions(boolean getProcedureReturnsFunctions); + + public abstract boolean getGetProceduresReturnsFunctions(); + + public abstract void setDetectCustomCollations(boolean detectCustomCollations); + + public abstract boolean getDetectCustomCollations(); + + String getConnectionAttributes() throws SQLException; + + public abstract String getServerRSAPublicKeyFile(); + + public abstract void setServerRSAPublicKeyFile(String serverRSAPublicKeyFile) throws SQLException; + + public abstract boolean getAllowPublicKeyRetrieval(); + + public abstract void setAllowPublicKeyRetrieval(boolean allowPublicKeyRetrieval) throws SQLException; + } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionPropertiesImpl.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionPropertiesImpl.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionPropertiesImpl.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,4859 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.sql.DriverPropertyInfo; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; + +import javax.naming.RefAddr; +import javax.naming.Reference; +import javax.naming.StringRefAddr; + +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.log.StandardLogger; + +/** + * Represents configurable properties for Connections and DataSources. Can also + * expose properties as JDBC DriverPropertyInfo if required as well. + * + * @author Mark Matthews + * @version $Id: ConnectionProperties.java,v 1.1.2.2 2005/05/17 14:58:56 + * mmatthews Exp $ + */ +public class ConnectionPropertiesImpl implements Serializable, ConnectionProperties { + + private static final long serialVersionUID = 4257801713007640580L; + + static class BooleanConnectionProperty extends ConnectionProperty implements Serializable { + + private static final long serialVersionUID = 2540132501709159404L; + + /** + * DOCUMENT ME! + * + * @param propertyNameToSet + * @param defaultValueToSet + * @param descriptionToSet + * DOCUMENT ME! + * @param sinceVersionToSet + * DOCUMENT ME! + */ + BooleanConnectionProperty(String propertyNameToSet, + boolean defaultValueToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + super(propertyNameToSet, Boolean.valueOf(defaultValueToSet), null, 0, + 0, descriptionToSet, sinceVersionToSet, category, + orderInCategory); + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#getAllowableValues() + */ + String[] getAllowableValues() { + return new String[] { "true", "false", "yes", "no" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + boolean getValueAsBoolean() { + return ((Boolean) this.valueAsObject).booleanValue(); + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#hasValueConstraints() + */ + boolean hasValueConstraints() { + return true; + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#initializeFrom(java.util.Properties) + */ + void initializeFrom(String extractedValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (extractedValue != null) { + validateStringValues(extractedValue, exceptionInterceptor); + + this.valueAsObject = Boolean.valueOf(extractedValue + .equalsIgnoreCase("TRUE") //$NON-NLS-1$ + || extractedValue.equalsIgnoreCase("YES")); //$NON-NLS-1$ + } else { + this.valueAsObject = this.defaultValue; + } + this.updateCount++; + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#isRangeBased() + */ + boolean isRangeBased() { + return false; + } + + void setValue(boolean valueFlag) { + this.valueAsObject = Boolean.valueOf(valueFlag); + this.updateCount++; + } + } + + static abstract class ConnectionProperty implements Serializable { + + static final long serialVersionUID = -6644853639584478367L; + + String[] allowableValues; + + String categoryName; + + Object defaultValue; + + int lowerBound; + + int order; + + String propertyName; + + String sinceVersion; + + int upperBound; + + Object valueAsObject; + + boolean required; + + String description; + + int updateCount = 0; + + public ConnectionProperty() {} + + ConnectionProperty(String propertyNameToSet, Object defaultValueToSet, + String[] allowableValuesToSet, int lowerBoundToSet, + int upperBoundToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + + this.description = descriptionToSet; + this.propertyName = propertyNameToSet; + this.defaultValue = defaultValueToSet; + this.valueAsObject = defaultValueToSet; + this.allowableValues = allowableValuesToSet; + this.lowerBound = lowerBoundToSet; + this.upperBound = upperBoundToSet; + this.required = false; + this.sinceVersion = sinceVersionToSet; + this.categoryName = category; + this.order = orderInCategory; + } + + String[] getAllowableValues() { + return this.allowableValues; + } + + /** + * @return Returns the categoryName. + */ + String getCategoryName() { + return this.categoryName; + } + + Object getDefaultValue() { + return this.defaultValue; + } + + int getLowerBound() { + return this.lowerBound; + } + + /** + * @return Returns the order. + */ + int getOrder() { + return this.order; + } + + String getPropertyName() { + return this.propertyName; + } + + int getUpperBound() { + return this.upperBound; + } + + Object getValueAsObject() { + return this.valueAsObject; + } + + int getUpdateCount() { + return this.updateCount; + } + + abstract boolean hasValueConstraints(); + + void initializeFrom(Properties extractFrom, ExceptionInterceptor exceptionInterceptor) throws SQLException { + String extractedValue = extractFrom.getProperty(getPropertyName()); + extractFrom.remove(getPropertyName()); + initializeFrom(extractedValue, exceptionInterceptor); + } + + void initializeFrom(Reference ref, ExceptionInterceptor exceptionInterceptor) throws SQLException { + RefAddr refAddr = ref.get(getPropertyName()); + + if (refAddr != null) { + String refContentAsString = (String) refAddr.getContent(); + + initializeFrom(refContentAsString, exceptionInterceptor); + } + } + + abstract void initializeFrom(String extractedValue, ExceptionInterceptor exceptionInterceptor) throws SQLException; + + abstract boolean isRangeBased(); + + /** + * @param categoryName + * The categoryName to set. + */ + void setCategoryName(String categoryName) { + this.categoryName = categoryName; + } + + /** + * @param order + * The order to set. + */ + void setOrder(int order) { + this.order = order; + } + + void setValueAsObject(Object obj) { + this.valueAsObject = obj; + this.updateCount++; + } + + void storeTo(Reference ref) { + if (getValueAsObject() != null) { + ref.add(new StringRefAddr(getPropertyName(), getValueAsObject() + .toString())); + } + } + + DriverPropertyInfo getAsDriverPropertyInfo() { + DriverPropertyInfo dpi = new DriverPropertyInfo(this.propertyName, null); + dpi.choices = getAllowableValues(); + dpi.value = (this.valueAsObject != null) ? this.valueAsObject.toString() : null; + dpi.required = this.required; + dpi.description = this.description; + + return dpi; + } + + + void validateStringValues(String valueToValidate, ExceptionInterceptor exceptionInterceptor) throws SQLException { + String[] validateAgainst = getAllowableValues(); + + if (valueToValidate == null) { + return; + } + + if ((validateAgainst == null) || (validateAgainst.length == 0)) { + return; + } + + for (int i = 0; i < validateAgainst.length; i++) { + if ((validateAgainst[i] != null) + && validateAgainst[i].equalsIgnoreCase(valueToValidate)) { + return; + } + } + + StringBuffer errorMessageBuf = new StringBuffer(); + + errorMessageBuf.append("The connection property '"); //$NON-NLS-1$ + errorMessageBuf.append(getPropertyName()); + errorMessageBuf.append("' only accepts values of the form: "); //$NON-NLS-1$ + + if (validateAgainst.length != 0) { + errorMessageBuf.append("'"); //$NON-NLS-1$ + errorMessageBuf.append(validateAgainst[0]); + errorMessageBuf.append("'"); //$NON-NLS-1$ + + for (int i = 1; i < (validateAgainst.length - 1); i++) { + errorMessageBuf.append(", "); //$NON-NLS-1$ + errorMessageBuf.append("'"); //$NON-NLS-1$ + errorMessageBuf.append(validateAgainst[i]); + errorMessageBuf.append("'"); //$NON-NLS-1$ + } + + errorMessageBuf.append(" or '"); //$NON-NLS-1$ + errorMessageBuf + .append(validateAgainst[validateAgainst.length - 1]); + errorMessageBuf.append("'"); //$NON-NLS-1$ + } + + errorMessageBuf.append(". The value '"); //$NON-NLS-1$ + errorMessageBuf.append(valueToValidate); + errorMessageBuf.append("' is not in this set."); //$NON-NLS-1$ + + throw SQLError.createSQLException(errorMessageBuf.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } + + static class IntegerConnectionProperty extends ConnectionProperty implements Serializable { + + private static final long serialVersionUID = -3004305481796850832L; + + int multiplier = 1; + + public IntegerConnectionProperty(String propertyNameToSet, + Object defaultValueToSet, String[] allowableValuesToSet, + int lowerBoundToSet, int upperBoundToSet, + String descriptionToSet, String sinceVersionToSet, + String category, int orderInCategory) { + super(propertyNameToSet, defaultValueToSet, allowableValuesToSet, + lowerBoundToSet, upperBoundToSet, descriptionToSet, sinceVersionToSet, + category, orderInCategory); + } + + IntegerConnectionProperty(String propertyNameToSet, + int defaultValueToSet, int lowerBoundToSet, + int upperBoundToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + super(propertyNameToSet, Integer.valueOf(defaultValueToSet), null, + lowerBoundToSet, upperBoundToSet, descriptionToSet, + sinceVersionToSet, category, orderInCategory); + } + + /** + * DOCUMENT ME! + * + * @param propertyNameToSet + * @param defaultValueToSet + * @param descriptionToSet + * @param sinceVersionToSet + * DOCUMENT ME! + */ + + IntegerConnectionProperty(String propertyNameToSet, + int defaultValueToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + this(propertyNameToSet, defaultValueToSet, 0, 0, descriptionToSet, + sinceVersionToSet, category, orderInCategory); + } + + /** + * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getAllowableValues() + */ + String[] getAllowableValues() { + return null; + } + + /** + * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getLowerBound() + */ + int getLowerBound() { + return this.lowerBound; + } + + /** + * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#getUpperBound() + */ + int getUpperBound() { + return this.upperBound; + } + + int getValueAsInt() { + return ((Integer) this.valueAsObject).intValue(); + } + + /** + * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#hasValueConstraints() + */ + boolean hasValueConstraints() { + return false; + } + + /** + * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#initializeFrom(java.lang.String) + */ + void initializeFrom(String extractedValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (extractedValue != null) { + try { + // Parse decimals, too + int intValue = (int) (Double.valueOf(extractedValue).doubleValue() * multiplier); + + setValue(intValue, extractedValue, exceptionInterceptor); + } catch (NumberFormatException nfe) { + throw SQLError.createSQLException("The connection property '" //$NON-NLS-1$ + + getPropertyName() + + "' only accepts integer values. The value '" //$NON-NLS-1$ + + extractedValue + + "' can not be converted to an integer.", //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } else { + this.valueAsObject = this.defaultValue; + } + this.updateCount++; + } + + /** + * @see com.mysql.jdbc.ConnectionProperties.ConnectionProperty#isRangeBased() + */ + boolean isRangeBased() { + return getUpperBound() != getLowerBound(); + } + + void setValue(int intValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + setValue(intValue, null, exceptionInterceptor); + } + + void setValue(int intValue, String valueAsString, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (isRangeBased()) { + if ((intValue < getLowerBound()) || (intValue > getUpperBound())) { + throw SQLError.createSQLException("The connection property '" + getPropertyName() + + "' only accepts integer values in the range of " + getLowerBound() + " - " + + getUpperBound() + ", the value '" + (valueAsString == null ? intValue : valueAsString) + + "' exceeds this range.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } + + this.valueAsObject = Integer.valueOf(intValue); + this.updateCount++; + } + } + + static public class LongConnectionProperty extends IntegerConnectionProperty { + + private static final long serialVersionUID = 6068572984340480895L; + + LongConnectionProperty(String propertyNameToSet, + long defaultValueToSet, long lowerBoundToSet, + long upperBoundToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + super(propertyNameToSet, Long.valueOf(defaultValueToSet), null, + (int)lowerBoundToSet, (int)upperBoundToSet, descriptionToSet, + sinceVersionToSet, category, orderInCategory); + } + + + LongConnectionProperty(String propertyNameToSet, + long defaultValueToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + this(propertyNameToSet, + defaultValueToSet, 0, + 0, descriptionToSet, + sinceVersionToSet, category, orderInCategory); + } + + void setValue(long longValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + setValue(longValue, null, exceptionInterceptor); + } + + void setValue(long longValue, String valueAsString, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (isRangeBased()) { + if ((longValue < getLowerBound()) || (longValue > getUpperBound())) { + throw SQLError.createSQLException("The connection property '" + getPropertyName() + + "' only accepts long integer values in the range of " + getLowerBound() + " - " + + getUpperBound() + ", the value '" + (valueAsString == null ? longValue : valueAsString) + + "' exceeds this range.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } + this.valueAsObject = Long.valueOf(longValue); + this.updateCount++; + } + + long getValueAsLong() { + return ((Long) this.valueAsObject).longValue(); + } + + void initializeFrom(String extractedValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (extractedValue != null) { + try { + // Parse decimals, too + long longValue = Double.valueOf(extractedValue).longValue(); + + setValue(longValue, extractedValue, exceptionInterceptor); + } catch (NumberFormatException nfe) { + throw SQLError.createSQLException("The connection property '" //$NON-NLS-1$ + + getPropertyName() + + "' only accepts long integer values. The value '" //$NON-NLS-1$ + + extractedValue + + "' can not be converted to a long integer.", //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } else { + this.valueAsObject = this.defaultValue; + } + this.updateCount++; + } + } + + static class MemorySizeConnectionProperty extends IntegerConnectionProperty implements Serializable { + + private static final long serialVersionUID = 7351065128998572656L; + + private String valueAsString; + + MemorySizeConnectionProperty(String propertyNameToSet, + int defaultValueToSet, int lowerBoundToSet, + int upperBoundToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + super(propertyNameToSet, defaultValueToSet, lowerBoundToSet, + upperBoundToSet, descriptionToSet, sinceVersionToSet, + category, orderInCategory); + } + + void initializeFrom(String extractedValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + valueAsString = extractedValue; + multiplier = 1; + + if (extractedValue != null) { + if (extractedValue.endsWith("k") //$NON-NLS-1$ + || extractedValue.endsWith("K") //$NON-NLS-1$ + || extractedValue.endsWith("kb") //$NON-NLS-1$ + || extractedValue.endsWith("Kb") //$NON-NLS-1$ + || extractedValue.endsWith("kB") //$NON-NLS-1$ + || extractedValue.endsWith("KB")) { //$NON-NLS-1$ + multiplier = 1024; + int indexOfK = StringUtils.indexOfIgnoreCase( + extractedValue, "k"); //$NON-NLS-1$ + extractedValue = extractedValue.substring(0, indexOfK); + } else if (extractedValue.endsWith("m") //$NON-NLS-1$ + || extractedValue.endsWith("M") //$NON-NLS-1$ + || extractedValue.endsWith("mb") //$NON-NLS-1$ + || extractedValue.endsWith("Mb") //$NON-NLS-1$ + || extractedValue.endsWith("mB") //$NON-NLS-1$ + || extractedValue.endsWith("MB")) { //$NON-NLS-1$ + multiplier = 1024 * 1024; + int indexOfM = StringUtils.indexOfIgnoreCase( + extractedValue, "m"); //$NON-NLS-1$ + extractedValue = extractedValue.substring(0, indexOfM); + } else if (extractedValue.endsWith("g") //$NON-NLS-1$ + || extractedValue.endsWith("G") //$NON-NLS-1$ + || extractedValue.endsWith("gb") //$NON-NLS-1$ + || extractedValue.endsWith("Gb") //$NON-NLS-1$ + || extractedValue.endsWith("gB") //$NON-NLS-1$ + || extractedValue.endsWith("GB")) { //$NON-NLS-1$ + multiplier = 1024 * 1024 * 1024; + int indexOfG = StringUtils.indexOfIgnoreCase( + extractedValue, "g"); //$NON-NLS-1$ + extractedValue = extractedValue.substring(0, indexOfG); + } + } + + super.initializeFrom(extractedValue, exceptionInterceptor); + } + + void setValue(String value, ExceptionInterceptor exceptionInterceptor) throws SQLException { + initializeFrom(value, exceptionInterceptor); + } + + String getValueAsString() { + return valueAsString; + } + } + + static class StringConnectionProperty extends ConnectionProperty implements Serializable { + + private static final long serialVersionUID = 5432127962785948272L; + + StringConnectionProperty(String propertyNameToSet, + String defaultValueToSet, String descriptionToSet, + String sinceVersionToSet, String category, int orderInCategory) { + this(propertyNameToSet, defaultValueToSet, null, descriptionToSet, + sinceVersionToSet, category, orderInCategory); + } + + /** + * DOCUMENT ME! + * + * @param propertyNameToSet + * @param defaultValueToSet + * @param allowableValuesToSet + * @param descriptionToSet + * @param sinceVersionToSet + * DOCUMENT ME! + */ + StringConnectionProperty(String propertyNameToSet, + String defaultValueToSet, String[] allowableValuesToSet, + String descriptionToSet, String sinceVersionToSet, + String category, int orderInCategory) { + super(propertyNameToSet, defaultValueToSet, allowableValuesToSet, + 0, 0, descriptionToSet, sinceVersionToSet, category, + orderInCategory); + } + + String getValueAsString() { + return (String) this.valueAsObject; + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#hasValueConstraints() + */ + boolean hasValueConstraints() { + return (this.allowableValues != null) + && (this.allowableValues.length > 0); + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#initializeFrom(java.util.Properties) + */ + void initializeFrom(String extractedValue, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (extractedValue != null) { + validateStringValues(extractedValue, exceptionInterceptor); + + this.valueAsObject = extractedValue; + } else { + this.valueAsObject = this.defaultValue; + } + this.updateCount++; + } + + /** + * @see com.mysql.jdbc.ConnectionPropertiesImpl.ConnectionProperty#isRangeBased() + */ + boolean isRangeBased() { + return false; + } + + void setValue(String valueFlag) { + this.valueAsObject = valueFlag; + this.updateCount++; + } + } + + private static final String CONNECTION_AND_AUTH_CATEGORY = Messages.getString("ConnectionProperties.categoryConnectionAuthentication"); //$NON-NLS-1$ + + private static final String NETWORK_CATEGORY = Messages.getString("ConnectionProperties.categoryNetworking"); //$NON-NLS-1$ + + private static final String DEBUGING_PROFILING_CATEGORY = Messages.getString("ConnectionProperties.categoryDebuggingProfiling"); //$NON-NLS-1$ + + private static final String HA_CATEGORY = Messages.getString("ConnectionProperties.categorryHA"); //$NON-NLS-1$ + + private static final String MISC_CATEGORY = Messages.getString("ConnectionProperties.categoryMisc"); //$NON-NLS-1$ + + private static final String PERFORMANCE_CATEGORY = Messages.getString("ConnectionProperties.categoryPerformance"); //$NON-NLS-1$ + + private static final String SECURITY_CATEGORY = Messages.getString("ConnectionProperties.categorySecurity"); //$NON-NLS-1$ + + private static final String[] PROPERTY_CATEGORIES = new String[] { + CONNECTION_AND_AUTH_CATEGORY, NETWORK_CATEGORY, + HA_CATEGORY, SECURITY_CATEGORY, + PERFORMANCE_CATEGORY, DEBUGING_PROFILING_CATEGORY, MISC_CATEGORY }; + + private static final ArrayList PROPERTY_LIST = new ArrayList(); + + // + // Yes, this looks goofy, but we're trying to avoid intern()ing here + // + private static final String STANDARD_LOGGER_NAME = StandardLogger.class.getName(); + + protected static final String ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL = "convertToNull"; //$NON-NLS-1$ + + protected static final String ZERO_DATETIME_BEHAVIOR_EXCEPTION = "exception"; //$NON-NLS-1$ + + protected static final String ZERO_DATETIME_BEHAVIOR_ROUND = "round"; //$NON-NLS-1$ + + static { + try { + java.lang.reflect.Field[] declaredFields = ConnectionPropertiesImpl.class + .getDeclaredFields(); + + for (int i = 0; i < declaredFields.length; i++) { + if (ConnectionPropertiesImpl.ConnectionProperty.class + .isAssignableFrom(declaredFields[i].getType())) { + PROPERTY_LIST.add(declaredFields[i]); + } + } + } catch (Exception ex) { + RuntimeException rtEx = new RuntimeException(); + rtEx.initCause(ex); + + throw rtEx; + } + } + + public ExceptionInterceptor getExceptionInterceptor() { + return null; + } + + /** + * Exposes all ConnectionPropertyInfo instances as DriverPropertyInfo + * + * @param info + * the properties to load into these ConnectionPropertyInfo + * instances + * @param slotsToReserve + * the number of DPI slots to reserve for 'standard' DPI + * properties (user, host, password, etc) + * @return a list of all ConnectionPropertyInfo instances, as + * DriverPropertyInfo + * @throws SQLException + * if an error occurs + */ + protected static DriverPropertyInfo[] exposeAsDriverPropertyInfo( + Properties info, int slotsToReserve) throws SQLException { + return (new ConnectionPropertiesImpl() { + private static final long serialVersionUID = 4257801713007640581L; + }).exposeAsDriverPropertyInfoInternal(info, slotsToReserve); + } + + private BooleanConnectionProperty allowLoadLocalInfile = new BooleanConnectionProperty( + "allowLoadLocalInfile", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.loadDataLocal"), //$NON-NLS-1$ + "3.0.3", SECURITY_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty allowMultiQueries = new BooleanConnectionProperty( + "allowMultiQueries", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.allowMultiQueries"), //$NON-NLS-1$ + "3.1.1", SECURITY_CATEGORY, 1); //$NON-NLS-1$ + + private BooleanConnectionProperty allowNanAndInf = new BooleanConnectionProperty( + "allowNanAndInf", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.allowNANandINF"), //$NON-NLS-1$ + "3.1.5", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty allowUrlInLocalInfile = new BooleanConnectionProperty( + "allowUrlInLocalInfile", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.allowUrlInLoadLocal"), //$NON-NLS-1$ + "3.1.4", SECURITY_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty alwaysSendSetIsolation = new BooleanConnectionProperty( + "alwaysSendSetIsolation", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.alwaysSendSetIsolation"), //$NON-NLS-1$ + "3.1.7", PERFORMANCE_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty autoClosePStmtStreams = new BooleanConnectionProperty( + "autoClosePStmtStreams", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.autoClosePstmtStreams"), //$NON-NLS-1$ + "3.1.12", //$NON-NLS-1$ + MISC_CATEGORY, + Integer.MIN_VALUE); + + private BooleanConnectionProperty allowMasterDownConnections = new BooleanConnectionProperty( + "allowMasterDownConnections", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.allowMasterDownConnections"), //$NON-NLS-1$ + "5.1.27", //$NON-NLS-1$ + HA_CATEGORY, + Integer.MAX_VALUE); + + private BooleanConnectionProperty autoDeserialize = new BooleanConnectionProperty( + "autoDeserialize", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.autoDeserialize"), //$NON-NLS-1$ + "3.1.5", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty autoGenerateTestcaseScript = new BooleanConnectionProperty( + "autoGenerateTestcaseScript", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.autoGenerateTestcaseScript"), "3.1.9", //$NON-NLS-1$ //$NON-NLS-2$ + DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private boolean autoGenerateTestcaseScriptAsBoolean = false; + + private BooleanConnectionProperty autoReconnect = new BooleanConnectionProperty( + "autoReconnect", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.autoReconnect"), //$NON-NLS-1$ + "1.1", HA_CATEGORY, 0); //$NON-NLS-1$ + + private BooleanConnectionProperty autoReconnectForPools = new BooleanConnectionProperty( + "autoReconnectForPools", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.autoReconnectForPools"), //$NON-NLS-1$ + "3.1.3", HA_CATEGORY, 1); //$NON-NLS-1$ + + private boolean autoReconnectForPoolsAsBoolean = false; + + private MemorySizeConnectionProperty blobSendChunkSize = new MemorySizeConnectionProperty( + "blobSendChunkSize", //$NON-NLS-1$ + 1024 * 1024, + 0, + 0, + Messages.getString("ConnectionProperties.blobSendChunkSize"), //$NON-NLS-1$ + "3.1.9", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty autoSlowLog = new BooleanConnectionProperty( + "autoSlowLog", true, + Messages.getString("ConnectionProperties.autoSlowLog"), + "5.1.4", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty blobsAreStrings = new BooleanConnectionProperty( + "blobsAreStrings", false, + "Should the driver always treat BLOBs as Strings - specifically to work around dubious metadata " + + "returned by the server for GROUP BY clauses?", + "5.0.8", MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty functionsNeverReturnBlobs = new BooleanConnectionProperty( + "functionsNeverReturnBlobs", false, + "Should the driver always treat data from functions returning BLOBs as Strings - specifically to work around dubious metadata " + + "returned by the server for GROUP BY clauses?", + "5.0.8", MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty cacheCallableStatements = new BooleanConnectionProperty( + "cacheCallableStmts", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.cacheCallableStatements"), //$NON-NLS-1$ + "3.1.2", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty cachePreparedStatements = new BooleanConnectionProperty( + "cachePrepStmts", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.cachePrepStmts"), //$NON-NLS-1$ + "3.0.10", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty cacheResultSetMetadata = new BooleanConnectionProperty( + "cacheResultSetMetadata", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.cacheRSMetadata"), //$NON-NLS-1$ + "3.1.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private boolean cacheResultSetMetaDataAsBoolean; + + private StringConnectionProperty serverConfigCacheFactory = new StringConnectionProperty("serverConfigCacheFactory", //$NON-NLS-1$ + PerVmServerConfigCacheFactory.class.getName(), Messages.getString("ConnectionProperties.serverConfigCacheFactory"), "5.1.1", PERFORMANCE_CATEGORY, 12); //$NON-NLS-1$ //$NON-NLS-2$ + + private BooleanConnectionProperty cacheServerConfiguration = new BooleanConnectionProperty( + "cacheServerConfiguration", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.cacheServerConfiguration"), //$NON-NLS-1$ + "3.1.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty callableStatementCacheSize = new IntegerConnectionProperty( + "callableStmtCacheSize", //$NON-NLS-1$ + 100, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.callableStmtCacheSize"), //$NON-NLS-1$ + "3.1.2", PERFORMANCE_CATEGORY, 5); //$NON-NLS-1$ + + private BooleanConnectionProperty capitalizeTypeNames = new BooleanConnectionProperty( + "capitalizeTypeNames", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.capitalizeTypeNames"), //$NON-NLS-1$ + "2.0.7", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty characterEncoding = new StringConnectionProperty( + "characterEncoding", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.characterEncoding"), //$NON-NLS-1$ + "1.1g", MISC_CATEGORY, 5); //$NON-NLS-1$ + + private String characterEncodingAsString = null; + + protected boolean characterEncodingIsAliasForSjis = false; + + private StringConnectionProperty characterSetResults = new StringConnectionProperty( + "characterSetResults", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.characterSetResults"), "3.0.13", //$NON-NLS-1$ //$NON-NLS-2$ + MISC_CATEGORY, 6); + + private StringConnectionProperty connectionAttributes = new StringConnectionProperty( + "connectionAttributes", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.connectionAttributes"), "5.1.25", //$NON-NLS-1$ //$NON-NLS-2$ + MISC_CATEGORY, 7); + + + private StringConnectionProperty clientInfoProvider = new StringConnectionProperty( + "clientInfoProvider", "com.mysql.jdbc.JDBC4CommentClientInfoProvider", //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.clientInfoProvider"), //$NON-NLS-1$ + "5.1.0", //$NON-NLS-1$ + DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty clobberStreamingResults = new BooleanConnectionProperty( + "clobberStreamingResults", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.clobberStreamingResults"), //$NON-NLS-1$ + "3.0.9", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty clobCharacterEncoding = new StringConnectionProperty( + "clobCharacterEncoding", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.clobCharacterEncoding"), //$NON-NLS-1$ + "5.0.0", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty compensateOnDuplicateKeyUpdateCounts = new BooleanConnectionProperty( + "compensateOnDuplicateKeyUpdateCounts", + false, + Messages.getString("ConnectionProperties.compensateOnDuplicateKeyUpdateCounts"), + "5.1.7", MISC_CATEGORY, Integer.MIN_VALUE); + private StringConnectionProperty connectionCollation = new StringConnectionProperty( + "connectionCollation", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.connectionCollation"), //$NON-NLS-1$ + "3.0.13", MISC_CATEGORY, 7); //$NON-NLS-1$ + + private StringConnectionProperty connectionLifecycleInterceptors = new StringConnectionProperty( + "connectionLifecycleInterceptors", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.connectionLifecycleInterceptors"), + "5.1.4", CONNECTION_AND_AUTH_CATEGORY, Integer.MAX_VALUE); + + private IntegerConnectionProperty connectTimeout = new IntegerConnectionProperty( + "connectTimeout", 0, 0, Integer.MAX_VALUE, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.connectTimeout"), //$NON-NLS-1$ + "3.0.1", CONNECTION_AND_AUTH_CATEGORY, 9); //$NON-NLS-1$ + + private BooleanConnectionProperty continueBatchOnError = new BooleanConnectionProperty( + "continueBatchOnError", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.continueBatchOnError"), //$NON-NLS-1$ + "3.0.3", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty createDatabaseIfNotExist = new BooleanConnectionProperty( + "createDatabaseIfNotExist", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.createDatabaseIfNotExist"), //$NON-NLS-1$ + "3.1.9", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty defaultFetchSize = new IntegerConnectionProperty("defaultFetchSize", 0, Messages.getString("ConnectionProperties.defaultFetchSize"), "3.1.9", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + // Think really long and hard about changing the default for this + // many, many applications have come to be acustomed to the + // latency profile of preparing stuff client-side, rather than + // prepare (round-trip), execute (round-trip), close (round-trip). + private BooleanConnectionProperty detectServerPreparedStmts = new BooleanConnectionProperty( + "useServerPrepStmts", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useServerPrepStmts"), //$NON-NLS-1$ + "3.1.0", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty dontTrackOpenResources = new BooleanConnectionProperty( + "dontTrackOpenResources", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.dontTrackOpenResources"), "3.1.7", PERFORMANCE_CATEGORY, //$NON-NLS-1$ //$NON-NLS-2$ + Integer.MIN_VALUE); + + private BooleanConnectionProperty dumpQueriesOnException = new BooleanConnectionProperty( + "dumpQueriesOnException", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.dumpQueriesOnException"), //$NON-NLS-1$ + "3.1.3", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty dynamicCalendars = new BooleanConnectionProperty( + "dynamicCalendars", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.dynamicCalendars"), //$NON-NLS-1$ + "3.1.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty elideSetAutoCommits = new BooleanConnectionProperty( + "elideSetAutoCommits", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.eliseSetAutoCommit"), //$NON-NLS-1$ + "3.1.3", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty emptyStringsConvertToZero = new BooleanConnectionProperty( + "emptyStringsConvertToZero", true, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.emptyStringsConvertToZero"), "3.1.8", //$NON-NLS-1$ //$NON-NLS-2$ + MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty emulateLocators = new BooleanConnectionProperty( + "emulateLocators", false, Messages.getString("ConnectionProperties.emulateLocators"), "3.1.0", MISC_CATEGORY, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Integer.MIN_VALUE); + + private BooleanConnectionProperty emulateUnsupportedPstmts = new BooleanConnectionProperty( + "emulateUnsupportedPstmts", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.emulateUnsupportedPstmts"), //$NON-NLS-1$ + "3.1.7", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty enablePacketDebug = new BooleanConnectionProperty( + "enablePacketDebug", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.enablePacketDebug"), //$NON-NLS-1$ + "3.1.3", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty enableQueryTimeouts = new BooleanConnectionProperty( + "enableQueryTimeouts", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.enableQueryTimeouts"), //$NON-NLS-1$ + "5.0.6", //$NON-NLS-1$ + PERFORMANCE_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty explainSlowQueries = new BooleanConnectionProperty( + "explainSlowQueries", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.explainSlowQueries"), //$NON-NLS-1$ + "3.1.2", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty exceptionInterceptors = new StringConnectionProperty( + "exceptionInterceptors", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.exceptionInterceptors"), + "5.1.8", MISC_CATEGORY, Integer.MIN_VALUE); + + /** When failed-over, set connection to read-only? */ + private BooleanConnectionProperty failOverReadOnly = new BooleanConnectionProperty( + "failOverReadOnly", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.failoverReadOnly"), //$NON-NLS-1$ + "3.0.12", HA_CATEGORY, 2); //$NON-NLS-1$ + + private BooleanConnectionProperty gatherPerformanceMetrics = new BooleanConnectionProperty( + "gatherPerfMetrics", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.gatherPerfMetrics"), //$NON-NLS-1$ + "3.1.2", DEBUGING_PROFILING_CATEGORY, 1); //$NON-NLS-1$ + + private BooleanConnectionProperty generateSimpleParameterMetadata = new BooleanConnectionProperty( + "generateSimpleParameterMetadata", false, Messages.getString("ConnectionProperties.generateSimpleParameterMetadata"), "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private boolean highAvailabilityAsBoolean = false; + + private BooleanConnectionProperty holdResultsOpenOverStatementClose = new BooleanConnectionProperty( + "holdResultsOpenOverStatementClose", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.holdRSOpenOverStmtClose"), //$NON-NLS-1$ + "3.1.7", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty includeInnodbStatusInDeadlockExceptions = new BooleanConnectionProperty( + "includeInnodbStatusInDeadlockExceptions", + false, + Messages.getString("ConnectionProperties.includeInnodbStatusInDeadlockExceptions"), + "5.0.7", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty includeThreadDumpInDeadlockExceptions = new BooleanConnectionProperty( + "includeThreadDumpInDeadlockExceptions", + false, + Messages.getString("ConnectionProperties.includeThreadDumpInDeadlockExceptions"), + "5.1.15", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty includeThreadNamesAsStatementComment = new BooleanConnectionProperty( + "includeThreadNamesAsStatementComment", + false, + Messages.getString("ConnectionProperties.includeThreadNamesAsStatementComment"), + "5.1.15", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty ignoreNonTxTables = new BooleanConnectionProperty( + "ignoreNonTxTables", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.ignoreNonTxTables"), //$NON-NLS-1$ + "3.0.9", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty initialTimeout = new IntegerConnectionProperty( + "initialTimeout", 2, 1, Integer.MAX_VALUE, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.initialTimeout"), //$NON-NLS-1$ + "1.1", HA_CATEGORY, 5); //$NON-NLS-1$ + + private BooleanConnectionProperty isInteractiveClient = new BooleanConnectionProperty( + "interactiveClient", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.interactiveClient"), //$NON-NLS-1$ + "3.1.0", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty jdbcCompliantTruncation = new BooleanConnectionProperty( + "jdbcCompliantTruncation", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.jdbcCompliantTruncation"), "3.1.2", MISC_CATEGORY, //$NON-NLS-1$ //$NON-NLS-2$ + Integer.MIN_VALUE); + + private boolean jdbcCompliantTruncationForReads = + this.jdbcCompliantTruncation.getValueAsBoolean(); + + protected MemorySizeConnectionProperty largeRowSizeThreshold = new MemorySizeConnectionProperty("largeRowSizeThreshold", + 2048, 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.largeRowSizeThreshold"), + "5.1.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); + + private StringConnectionProperty loadBalanceStrategy = new StringConnectionProperty( + "loadBalanceStrategy", //$NON-NLS-1$ + "random", //$NON-NLS-1$ + null, //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.loadBalanceStrategy"), //$NON-NLS-1$ + "5.0.6", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty loadBalanceBlacklistTimeout = new IntegerConnectionProperty( + "loadBalanceBlacklistTimeout", 0, //$NON-NLS-1$ + 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.loadBalanceBlacklistTimeout"), //$NON-NLS-1$ + "5.1.0", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty loadBalancePingTimeout = new IntegerConnectionProperty( + "loadBalancePingTimeout", 0, //$NON-NLS-1$ + 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.loadBalancePingTimeout"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty loadBalanceValidateConnectionOnSwapServer = new BooleanConnectionProperty( + "loadBalanceValidateConnectionOnSwapServer", + false, + Messages.getString("ConnectionProperties.loadBalanceValidateConnectionOnSwapServer"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty loadBalanceConnectionGroup = new StringConnectionProperty( + "loadBalanceConnectionGroup", //$NON-NLS-1$ + null, //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.loadBalanceConnectionGroup"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty loadBalanceExceptionChecker = new StringConnectionProperty( + "loadBalanceExceptionChecker", //$NON-NLS-1$ + "com.mysql.jdbc.StandardLoadBalanceExceptionChecker", //$NON-NLS-1$ + null, //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.loadBalanceExceptionChecker"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty loadBalanceSQLStateFailover = new StringConnectionProperty( + "loadBalanceSQLStateFailover", //$NON-NLS-1$ + null, //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.loadBalanceSQLStateFailover"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty loadBalanceSQLExceptionSubclassFailover = new StringConnectionProperty( + "loadBalanceSQLExceptionSubclassFailover", //$NON-NLS-1$ + null, //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.loadBalanceSQLExceptionSubclassFailover"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty loadBalanceEnableJMX = new BooleanConnectionProperty( + "loadBalanceEnableJMX", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.loadBalanceEnableJMX"), //$NON-NLS-1$ + "5.1.13", MISC_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty loadBalanceAutoCommitStatementRegex = new StringConnectionProperty( + "loadBalanceAutoCommitStatementRegex", //$NON-NLS-1$ + null, //$NON-NLS-1$ //$NON-NLS-2$ + Messages.getString("ConnectionProperties.loadBalanceAutoCommitStatementRegex"), //$NON-NLS-1$ + "5.1.15", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty loadBalanceAutoCommitStatementThreshold = new IntegerConnectionProperty( + "loadBalanceAutoCommitStatementThreshold", 0, //$NON-NLS-1$ + 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.loadBalanceAutoCommitStatementThreshold"), //$NON-NLS-1$ + "5.1.15", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + + private StringConnectionProperty localSocketAddress = new StringConnectionProperty("localSocketAddress", //$NON-NLS-1$ + null, Messages.getString("ConnectionProperties.localSocketAddress"), //$NON-NLS-1$ + "5.0.5", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private MemorySizeConnectionProperty locatorFetchBufferSize = new MemorySizeConnectionProperty( + "locatorFetchBufferSize", //$NON-NLS-1$ + 1024 * 1024, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.locatorFetchBufferSize"), //$NON-NLS-1$ + "3.2.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty loggerClassName = new StringConnectionProperty( + "logger", STANDARD_LOGGER_NAME, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.logger", new Object[] {Log.class.getName(), STANDARD_LOGGER_NAME}), //$NON-NLS-1$ + "3.1.1", DEBUGING_PROFILING_CATEGORY, //$NON-NLS-1$ //$NON-NLS-2$ + 0); + + private BooleanConnectionProperty logSlowQueries = new BooleanConnectionProperty( + "logSlowQueries", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.logSlowQueries"), //$NON-NLS-1$ + "3.1.2", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty logXaCommands = new BooleanConnectionProperty( + "logXaCommands", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.logXaCommands"), //$NON-NLS-1$ + "5.0.5", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty maintainTimeStats = new BooleanConnectionProperty( + "maintainTimeStats", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.maintainTimeStats"), "3.1.9", PERFORMANCE_CATEGORY, //$NON-NLS-1$ //$NON-NLS-2$ + Integer.MAX_VALUE); + + private boolean maintainTimeStatsAsBoolean = true; + + private IntegerConnectionProperty maxQuerySizeToLog = new IntegerConnectionProperty( + "maxQuerySizeToLog", //$NON-NLS-1$ + 2048, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.maxQuerySizeToLog"), //$NON-NLS-1$ + "3.1.3", DEBUGING_PROFILING_CATEGORY, 4); //$NON-NLS-1$ + + private IntegerConnectionProperty maxReconnects = new IntegerConnectionProperty( + "maxReconnects", //$NON-NLS-1$ + 3, + 1, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.maxReconnects"), //$NON-NLS-1$ + "1.1", HA_CATEGORY, 4); //$NON-NLS-1$ + + private IntegerConnectionProperty retriesAllDown = new IntegerConnectionProperty( + "retriesAllDown", //$NON-NLS-1$ + 120, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.retriesAllDown"), //$NON-NLS-1$ + "5.1.6", HA_CATEGORY, 4); //$NON-NLS-1$ + + private IntegerConnectionProperty maxRows = new IntegerConnectionProperty( + "maxRows", -1, -1, Integer.MAX_VALUE, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.maxRows"), //$NON-NLS-1$ + Messages.getString("ConnectionProperties.allVersions"), MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private int maxRowsAsInt = -1; + + private IntegerConnectionProperty metadataCacheSize = new IntegerConnectionProperty( + "metadataCacheSize", //$NON-NLS-1$ + 50, + 1, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.metadataCacheSize"), //$NON-NLS-1$ + "3.1.1", PERFORMANCE_CATEGORY, 5); //$NON-NLS-1$ + + private IntegerConnectionProperty netTimeoutForStreamingResults = new IntegerConnectionProperty( + "netTimeoutForStreamingResults", 600, //$NON-NLS-1$ + 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.netTimeoutForStreamingResults"), //$NON-NLS-1$ + "5.1.0", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty noAccessToProcedureBodies = new BooleanConnectionProperty( + "noAccessToProcedureBodies", + false, + "When determining procedure parameter types for CallableStatements, and the connected user " + + " can't access procedure bodies through \"SHOW CREATE PROCEDURE\" or select on mysql.proc " + + " should the driver instead create basic metadata (all parameters reported as IN VARCHARs," + + " but allowing registerOutParameter() to be called on them anyway) instead " + + " of throwing an exception?", + "5.0.3", MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty noDatetimeStringSync = new BooleanConnectionProperty( + "noDatetimeStringSync", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.noDatetimeStringSync"), //$NON-NLS-1$ + "3.1.7", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty noTimezoneConversionForTimeType = new BooleanConnectionProperty( + "noTimezoneConversionForTimeType", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.noTzConversionForTimeType"), //$NON-NLS-1$ + "5.0.0", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty nullCatalogMeansCurrent = new BooleanConnectionProperty( + "nullCatalogMeansCurrent", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.nullCatalogMeansCurrent"), //$NON-NLS-1$ + "3.1.8", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty nullNamePatternMatchesAll = new BooleanConnectionProperty( + "nullNamePatternMatchesAll", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.nullNamePatternMatchesAll"), //$NON-NLS-1$ + "3.1.8", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty packetDebugBufferSize = new IntegerConnectionProperty( + "packetDebugBufferSize", //$NON-NLS-1$ + 20, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.packetDebugBufferSize"), //$NON-NLS-1$ + "3.1.3", DEBUGING_PROFILING_CATEGORY, 7); //$NON-NLS-1$ + + private BooleanConnectionProperty padCharsWithSpace = new BooleanConnectionProperty( + "padCharsWithSpace", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.padCharsWithSpace"), //$NON-NLS-1$ + "5.0.6", //$NON-NLS-1$ + MISC_CATEGORY, + Integer.MIN_VALUE); + + private BooleanConnectionProperty paranoid = new BooleanConnectionProperty( + "paranoid", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.paranoid"), //$NON-NLS-1$ + "3.0.1", SECURITY_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty pedantic = new BooleanConnectionProperty( + "pedantic", false, Messages.getString("ConnectionProperties.pedantic"), "3.0.0", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty pinGlobalTxToPhysicalConnection = new BooleanConnectionProperty( + "pinGlobalTxToPhysicalConnection", false, Messages.getString("ConnectionProperties.pinGlobalTxToPhysicalConnection"), //$NON-NLS-1$ + "5.0.1", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty populateInsertRowWithDefaultValues = new BooleanConnectionProperty( + "populateInsertRowWithDefaultValues", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.populateInsertRowWithDefaultValues"), //$NON-NLS-1$ + "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty preparedStatementCacheSize = new IntegerConnectionProperty( + "prepStmtCacheSize", 25, 0, Integer.MAX_VALUE, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.prepStmtCacheSize"), //$NON-NLS-1$ + "3.0.10", PERFORMANCE_CATEGORY, 10); //$NON-NLS-1$ + + private IntegerConnectionProperty preparedStatementCacheSqlLimit = new IntegerConnectionProperty( + "prepStmtCacheSqlLimit", //$NON-NLS-1$ + 256, + 1, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.prepStmtCacheSqlLimit"), //$NON-NLS-1$ + "3.0.10", PERFORMANCE_CATEGORY, 11); //$NON-NLS-1$ + + private StringConnectionProperty parseInfoCacheFactory = new StringConnectionProperty("parseInfoCacheFactory", //$NON-NLS-1$ + PerConnectionLRUFactory.class.getName(), Messages.getString("ConnectionProperties.parseInfoCacheFactory"), "5.1.1", PERFORMANCE_CATEGORY, 12); //$NON-NLS-1$ //$NON-NLS-2$ + + private BooleanConnectionProperty processEscapeCodesForPrepStmts = + new BooleanConnectionProperty("processEscapeCodesForPrepStmts", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.processEscapeCodesForPrepStmts"), //$NON-NLS-1$ + "3.1.12", //$NON-NLS-1$ + MISC_CATEGORY, Integer.MIN_VALUE); + + private StringConnectionProperty profilerEventHandler = new StringConnectionProperty( + "profilerEventHandler", + "com.mysql.jdbc.profiler.LoggingProfilerEventHandler", + Messages.getString("ConnectionProperties.profilerEventHandler"), + "5.1.6", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty profileSql = new StringConnectionProperty( + "profileSql", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.profileSqlDeprecated"), //$NON-NLS-1$ + "2.0.14", DEBUGING_PROFILING_CATEGORY, 3); //$NON-NLS-1$ + + private BooleanConnectionProperty profileSQL = new BooleanConnectionProperty( + "profileSQL", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.profileSQL"), //$NON-NLS-1$ + "3.1.0", DEBUGING_PROFILING_CATEGORY, 1); //$NON-NLS-1$ + + private boolean profileSQLAsBoolean = false; + + private StringConnectionProperty propertiesTransform = new StringConnectionProperty( + NonRegisteringDriver.PROPERTIES_TRANSFORM_KEY, + null, + Messages.getString("ConnectionProperties.connectionPropertiesTransform"), //$NON-NLS-1$ + "3.1.4", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty queriesBeforeRetryMaster = new IntegerConnectionProperty( + "queriesBeforeRetryMaster", //$NON-NLS-1$ + 50, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.queriesBeforeRetryMaster"), //$NON-NLS-1$ + "3.0.2", HA_CATEGORY, 7); //$NON-NLS-1$ + + private BooleanConnectionProperty queryTimeoutKillsConnection = new BooleanConnectionProperty( + "queryTimeoutKillsConnection", false, + Messages.getString("ConnectionProperties.queryTimeoutKillsConnection"), "5.1.9", MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty reconnectAtTxEnd = new BooleanConnectionProperty( + "reconnectAtTxEnd", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.reconnectAtTxEnd"), "3.0.10", //$NON-NLS-1$ //$NON-NLS-2$ + HA_CATEGORY, 4); + + private boolean reconnectTxAtEndAsBoolean = false; + + private BooleanConnectionProperty relaxAutoCommit = new BooleanConnectionProperty( + "relaxAutoCommit", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.relaxAutoCommit"), //$NON-NLS-1$ + "2.0.13", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty reportMetricsIntervalMillis = new IntegerConnectionProperty( + "reportMetricsIntervalMillis", //$NON-NLS-1$ + 30000, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.reportMetricsIntervalMillis"), //$NON-NLS-1$ + "3.1.2", DEBUGING_PROFILING_CATEGORY, 3); //$NON-NLS-1$ + + private BooleanConnectionProperty requireSSL = new BooleanConnectionProperty( + "requireSSL", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.requireSSL"), //$NON-NLS-1$ + "3.1.0", SECURITY_CATEGORY, 3); //$NON-NLS-1$ + + private StringConnectionProperty resourceId = new StringConnectionProperty( + "resourceId", //$NON-NLS-1$ + null, Messages.getString("ConnectionProperties.resourceId"), //$NON-NLS-1$ + "5.0.1", //$NON-NLS-1$ + HA_CATEGORY, + Integer.MIN_VALUE); + + private IntegerConnectionProperty resultSetSizeThreshold = new IntegerConnectionProperty("resultSetSizeThreshold", 100, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.resultSetSizeThreshold"), "5.0.5", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ //$NON-NLS-2$ + + private BooleanConnectionProperty retainStatementAfterResultSetClose = new BooleanConnectionProperty( + "retainStatementAfterResultSetClose", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.retainStatementAfterResultSetClose"), //$NON-NLS-1$ + "3.1.11", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty rewriteBatchedStatements = new BooleanConnectionProperty( + "rewriteBatchedStatements", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.rewriteBatchedStatements"), //$NON-NLS-1$ + "3.1.13", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty rollbackOnPooledClose = new BooleanConnectionProperty( + "rollbackOnPooledClose", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.rollbackOnPooledClose"), //$NON-NLS-1$ + "3.0.15", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty roundRobinLoadBalance = new BooleanConnectionProperty( + "roundRobinLoadBalance", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.roundRobinLoadBalance"), //$NON-NLS-1$ + "3.1.2", HA_CATEGORY, 5); //$NON-NLS-1$ + + private BooleanConnectionProperty runningCTS13 = new BooleanConnectionProperty( + "runningCTS13", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.runningCTS13"), //$NON-NLS-1$ + "3.1.7", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty secondsBeforeRetryMaster = new IntegerConnectionProperty( + "secondsBeforeRetryMaster", //$NON-NLS-1$ + 30, + 1, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.secondsBeforeRetryMaster"), //$NON-NLS-1$ + "3.0.2", HA_CATEGORY, 8); //$NON-NLS-1$ + + private IntegerConnectionProperty selfDestructOnPingSecondsLifetime = new IntegerConnectionProperty( + "selfDestructOnPingSecondsLifetime", + 0, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.selfDestructOnPingSecondsLifetime"), + "5.1.6", HA_CATEGORY, Integer.MAX_VALUE); + + private IntegerConnectionProperty selfDestructOnPingMaxOperations = new IntegerConnectionProperty( + "selfDestructOnPingMaxOperations", + 0, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.selfDestructOnPingMaxOperations"), + "5.1.6", HA_CATEGORY, Integer.MAX_VALUE); + + private BooleanConnectionProperty replicationEnableJMX = new BooleanConnectionProperty( + "replicationEnableJMX", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.loadBalanceEnableJMX"), //$NON-NLS-1$ + "5.1.27", HA_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty serverTimezone = new StringConnectionProperty( + "serverTimezone", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.serverTimezone"), //$NON-NLS-1$ + "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty sessionVariables = new StringConnectionProperty( + "sessionVariables", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.sessionVariables"), "3.1.8", //$NON-NLS-1$ //$NON-NLS-2$ + MISC_CATEGORY, Integer.MAX_VALUE); + + private IntegerConnectionProperty slowQueryThresholdMillis = new IntegerConnectionProperty( + "slowQueryThresholdMillis", //$NON-NLS-1$ + 2000, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.slowQueryThresholdMillis"), //$NON-NLS-1$ + "3.1.2", DEBUGING_PROFILING_CATEGORY, 9); //$NON-NLS-1$ + + private LongConnectionProperty slowQueryThresholdNanos = new LongConnectionProperty( + "slowQueryThresholdNanos", //$NON-NLS-1$ + 0, + Messages.getString("ConnectionProperties.slowQueryThresholdNanos"), //$NON-NLS-1$ + "5.0.7", //$NON-NLS-1$ + DEBUGING_PROFILING_CATEGORY, + 10); + + private StringConnectionProperty socketFactoryClassName = new StringConnectionProperty( + "socketFactory", //$NON-NLS-1$ + StandardSocketFactory.class.getName(), + Messages.getString("ConnectionProperties.socketFactory"), //$NON-NLS-1$ + "3.0.3", CONNECTION_AND_AUTH_CATEGORY, 4); //$NON-NLS-1$ + + private IntegerConnectionProperty socketTimeout = new IntegerConnectionProperty( + "socketTimeout", //$NON-NLS-1$ + 0, + 0, + Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.socketTimeout"), //$NON-NLS-1$ + "3.0.1", CONNECTION_AND_AUTH_CATEGORY, 10); //$NON-NLS-1$ + + private StringConnectionProperty statementInterceptors = new StringConnectionProperty("statementInterceptors", //$NON-NLS-1$ + null, Messages.getString("ConnectionProperties.statementInterceptors"), "5.1.1", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ //$NON-NLS-2$ + + private BooleanConnectionProperty strictFloatingPoint = new BooleanConnectionProperty( + "strictFloatingPoint", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.strictFloatingPoint"), "3.0.0", //$NON-NLS-1$ //$NON-NLS-2$ + MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty strictUpdates = new BooleanConnectionProperty( + "strictUpdates", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.strictUpdates"), //$NON-NLS-1$ + "3.0.4", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty overrideSupportsIntegrityEnhancementFacility = + new BooleanConnectionProperty("overrideSupportsIntegrityEnhancementFacility", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.overrideSupportsIEF"), //$NON-NLS-1$ + "3.1.12", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty tcpNoDelay = new BooleanConnectionProperty( + StandardSocketFactory.TCP_NO_DELAY_PROPERTY_NAME, + Boolean.valueOf(StandardSocketFactory.TCP_NO_DELAY_DEFAULT_VALUE).booleanValue(), + Messages.getString("ConnectionProperties.tcpNoDelay"), //$NON-NLS-1$ + "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty tcpKeepAlive = new BooleanConnectionProperty( + StandardSocketFactory.TCP_KEEP_ALIVE_PROPERTY_NAME, + Boolean.valueOf(StandardSocketFactory.TCP_KEEP_ALIVE_DEFAULT_VALUE).booleanValue(), + Messages.getString("ConnectionProperties.tcpKeepAlive"), //$NON-NLS-1$ + "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty tcpRcvBuf = new IntegerConnectionProperty( + StandardSocketFactory.TCP_RCV_BUF_PROPERTY_NAME, + Integer.parseInt(StandardSocketFactory.TCP_RCV_BUF_DEFAULT_VALUE), + 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.tcpSoRcvBuf"), //$NON-NLS-1$ + "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty tcpSndBuf = new IntegerConnectionProperty( + StandardSocketFactory.TCP_SND_BUF_PROPERTY_NAME, + Integer.parseInt(StandardSocketFactory.TCP_SND_BUF_DEFAULT_VALUE), + 0, Integer.MAX_VALUE, + Messages.getString("ConnectionProperties.tcpSoSndBuf"), //$NON-NLS-1$ + "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private IntegerConnectionProperty tcpTrafficClass = new IntegerConnectionProperty( + StandardSocketFactory.TCP_TRAFFIC_CLASS_PROPERTY_NAME, + Integer.parseInt(StandardSocketFactory.TCP_TRAFFIC_CLASS_DEFAULT_VALUE), + 0, 255, + Messages.getString("ConnectionProperties.tcpTrafficClass"), //$NON-NLS-1$ + "5.0.7", NETWORK_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty tinyInt1isBit = new BooleanConnectionProperty( + "tinyInt1isBit", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.tinyInt1isBit"), //$NON-NLS-1$ + "3.0.16", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + protected BooleanConnectionProperty traceProtocol = new BooleanConnectionProperty( + "traceProtocol", false, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.traceProtocol"), "3.1.2", //$NON-NLS-1$ //$NON-NLS-2$ + DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty treatUtilDateAsTimestamp = new BooleanConnectionProperty( + "treatUtilDateAsTimestamp", true, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.treatUtilDateAsTimestamp"), //$NON-NLS-1$ + "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty transformedBitIsBoolean = new BooleanConnectionProperty( + "transformedBitIsBoolean", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.transformedBitIsBoolean"), //$NON-NLS-1$ + "3.1.9", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useBlobToStoreUTF8OutsideBMP = new BooleanConnectionProperty( + "useBlobToStoreUTF8OutsideBMP", + false, + Messages.getString("ConnectionProperties.useBlobToStoreUTF8OutsideBMP"), //$NON-NLS-1$ + "5.1.3", MISC_CATEGORY, 128); + + private StringConnectionProperty utf8OutsideBmpExcludedColumnNamePattern = new StringConnectionProperty( + "utf8OutsideBmpExcludedColumnNamePattern", + null, + Messages.getString("ConnectionProperties.utf8OutsideBmpExcludedColumnNamePattern"), //$NON-NLS-1$ + "5.1.3", MISC_CATEGORY, 129); + + private StringConnectionProperty utf8OutsideBmpIncludedColumnNamePattern = new StringConnectionProperty( + "utf8OutsideBmpIncludedColumnNamePattern", + null, + Messages.getString("ConnectionProperties.utf8OutsideBmpIncludedColumnNamePattern"), //$NON-NLS-1$ + "5.1.3", MISC_CATEGORY, 129); + + private BooleanConnectionProperty useCompression = new BooleanConnectionProperty( + "useCompression", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useCompression"), //$NON-NLS-1$ + "3.0.17", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useColumnNamesInFindColumn = new BooleanConnectionProperty( + "useColumnNamesInFindColumn", + false, + Messages.getString("ConnectionProperties.useColumnNamesInFindColumn"), //$NON-NLS-1$ + "5.1.7", MISC_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty useConfigs = new StringConnectionProperty( + "useConfigs", //$NON-NLS-1$ + null, + Messages.getString("ConnectionProperties.useConfigs"), //$NON-NLS-1$ + "3.1.5", CONNECTION_AND_AUTH_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useCursorFetch = new BooleanConnectionProperty( + "useCursorFetch", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useCursorFetch"), //$NON-NLS-1$ + "5.0.0", PERFORMANCE_CATEGORY, Integer.MAX_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useDynamicCharsetInfo = new BooleanConnectionProperty( + "useDynamicCharsetInfo", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useDynamicCharsetInfo") //$NON-NLS-1$ + , "5.0.6", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useDirectRowUnpack = new BooleanConnectionProperty( + "useDirectRowUnpack", + true, "Use newer result set row unpacking code that skips a copy from network buffers " + + " to a MySQL packet instance and instead reads directly into the result set row data buffers.", + "5.1.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty useFastIntParsing = new BooleanConnectionProperty( + "useFastIntParsing", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useFastIntParsing"), //$NON-NLS-1$ + "3.1.4", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useFastDateParsing = new BooleanConnectionProperty( + "useFastDateParsing", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useFastDateParsing"), //$NON-NLS-1$ + "5.0.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useHostsInPrivileges = new BooleanConnectionProperty( + "useHostsInPrivileges", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useHostsInPrivileges"), //$NON-NLS-1$ + "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + private BooleanConnectionProperty useInformationSchema = new BooleanConnectionProperty( + "useInformationSchema", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useInformationSchema"), //$NON-NLS-1$ + "5.0.0", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + private BooleanConnectionProperty useJDBCCompliantTimezoneShift = new BooleanConnectionProperty( + "useJDBCCompliantTimezoneShift", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useJDBCCompliantTimezoneShift"), //$NON-NLS-1$ + "5.0.0", //$NON-NLS-1$ + MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty useLocalSessionState = new BooleanConnectionProperty( + "useLocalSessionState", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useLocalSessionState"), //$NON-NLS-1$ + "3.1.7", PERFORMANCE_CATEGORY, 5); //$NON-NLS-1$ + + private BooleanConnectionProperty useLocalTransactionState = new BooleanConnectionProperty( + "useLocalTransactionState", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useLocalTransactionState"), + "5.1.7", PERFORMANCE_CATEGORY, 6); + + private BooleanConnectionProperty useLegacyDatetimeCode = new BooleanConnectionProperty( + "useLegacyDatetimeCode", + true, + Messages.getString("ConnectionProperties.useLegacyDatetimeCode"), + "5.1.6", MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty useNanosForElapsedTime = new BooleanConnectionProperty( + "useNanosForElapsedTime", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useNanosForElapsedTime"), //$NON-NLS-1$ + "5.0.7", //$NON-NLS-1$ + DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty useOldAliasMetadataBehavior = new BooleanConnectionProperty( + "useOldAliasMetadataBehavior", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useOldAliasMetadataBehavior"), //$NON-NLS-1$ + "5.0.4", //$NON-NLS-1$ + MISC_CATEGORY, + Integer.MIN_VALUE); + + private BooleanConnectionProperty useOldUTF8Behavior = new BooleanConnectionProperty( + "useOldUTF8Behavior", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useOldUtf8Behavior"), //$NON-NLS-1$ + "3.1.6", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private boolean useOldUTF8BehaviorAsBoolean = false; + + private BooleanConnectionProperty useOnlyServerErrorMessages = new BooleanConnectionProperty( + "useOnlyServerErrorMessages", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useOnlyServerErrorMessages"), //$NON-NLS-1$ + "3.0.15", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useReadAheadInput = new BooleanConnectionProperty( + "useReadAheadInput", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useReadAheadInput"), //$NON-NLS-1$ + "3.1.5", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useSqlStateCodes = new BooleanConnectionProperty( + "useSqlStateCodes", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useSqlStateCodes"), //$NON-NLS-1$ + "3.1.3", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useSSL = new BooleanConnectionProperty( + "useSSL", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useSSL"), //$NON-NLS-1$ + "3.0.2", SECURITY_CATEGORY, 2); //$NON-NLS-1$ + + private BooleanConnectionProperty useSSPSCompatibleTimezoneShift = new BooleanConnectionProperty( + "useSSPSCompatibleTimezoneShift", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useSSPSCompatibleTimezoneShift"), //$NON-NLS-1$ + "5.0.5", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useStreamLengthsInPrepStmts = new BooleanConnectionProperty( + "useStreamLengthsInPrepStmts", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useStreamLengthsInPrepStmts"), //$NON-NLS-1$ + "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useTimezone = new BooleanConnectionProperty( + "useTimezone", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useTimezone"), //$NON-NLS-1$ + "3.0.2", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useUltraDevWorkAround = new BooleanConnectionProperty( + "ultraDevHack", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.ultraDevHack"), //$NON-NLS-1$ + "2.0.3", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useUnbufferedInput = new BooleanConnectionProperty( + "useUnbufferedInput", true, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.useUnbufferedInput"), //$NON-NLS-1$ + "3.0.11", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private BooleanConnectionProperty useUnicode = new BooleanConnectionProperty( + "useUnicode", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.useUnicode"), //$NON-NLS-1$ + "1.1g", MISC_CATEGORY, 0); //$NON-NLS-1$ + + // Cache these values, they are 'hot' + private boolean useUnicodeAsBoolean = true; + + private BooleanConnectionProperty useUsageAdvisor = new BooleanConnectionProperty( + "useUsageAdvisor", //$NON-NLS-1$ + false, + Messages.getString("ConnectionProperties.useUsageAdvisor"), //$NON-NLS-1$ + "3.1.1", DEBUGING_PROFILING_CATEGORY, 10); //$NON-NLS-1$ + + private boolean useUsageAdvisorAsBoolean = false; + + private BooleanConnectionProperty yearIsDateType = new BooleanConnectionProperty( + "yearIsDateType", //$NON-NLS-1$ + true, + Messages.getString("ConnectionProperties.yearIsDateType"), //$NON-NLS-1$ + "3.1.9", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ + + private StringConnectionProperty zeroDateTimeBehavior = new StringConnectionProperty( + "zeroDateTimeBehavior", //$NON-NLS-1$ + ZERO_DATETIME_BEHAVIOR_EXCEPTION, + new String[] { ZERO_DATETIME_BEHAVIOR_EXCEPTION, + ZERO_DATETIME_BEHAVIOR_ROUND, + ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL }, + Messages.getString("ConnectionProperties.zeroDateTimeBehavior", new Object[] {ZERO_DATETIME_BEHAVIOR_EXCEPTION, ZERO_DATETIME_BEHAVIOR_ROUND,ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL}), //$NON-NLS-1$ + "3.1.4", //$NON-NLS-1$ //$NON-NLS-2$ + MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty useJvmCharsetConverters = new BooleanConnectionProperty("useJvmCharsetConverters", //$NON-NLS-1$ + false, Messages.getString("ConnectionProperties.useJvmCharsetConverters"), "5.0.1", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ //$NON-NLS-2$ + + private BooleanConnectionProperty useGmtMillisForDatetimes = new BooleanConnectionProperty("useGmtMillisForDatetimes", false, Messages.getString("ConnectionProperties.useGmtMillisForDatetimes"), "3.1.12", MISC_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + private BooleanConnectionProperty dumpMetadataOnColumnNotFound = new BooleanConnectionProperty("dumpMetadataOnColumnNotFound", false, Messages.getString("ConnectionProperties.dumpMetadataOnColumnNotFound"), "3.1.13", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + // SSL Options + + private StringConnectionProperty clientCertificateKeyStoreUrl = new StringConnectionProperty( + "clientCertificateKeyStoreUrl", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.clientCertificateKeyStoreUrl"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$ + SECURITY_CATEGORY, 5); + + private StringConnectionProperty trustCertificateKeyStoreUrl = new StringConnectionProperty( + "trustCertificateKeyStoreUrl", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.trustCertificateKeyStoreUrl"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$ + SECURITY_CATEGORY, 8); + + private StringConnectionProperty clientCertificateKeyStoreType = new StringConnectionProperty( + "clientCertificateKeyStoreType", "JKS", //$NON-NLS-1$ + Messages.getString("ConnectionProperties.clientCertificateKeyStoreType"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$ + SECURITY_CATEGORY, 6); + + private StringConnectionProperty clientCertificateKeyStorePassword = new StringConnectionProperty( + "clientCertificateKeyStorePassword", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.clientCertificateKeyStorePassword"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$ + SECURITY_CATEGORY, 7); + + private StringConnectionProperty trustCertificateKeyStoreType = new StringConnectionProperty( + "trustCertificateKeyStoreType", "JKS", //$NON-NLS-1$ + Messages.getString("ConnectionProperties.trustCertificateKeyStoreType"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$ + SECURITY_CATEGORY, 9); + + private StringConnectionProperty trustCertificateKeyStorePassword = new StringConnectionProperty( + "trustCertificateKeyStorePassword", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.trustCertificateKeyStorePassword"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$ + SECURITY_CATEGORY, 10); + + private BooleanConnectionProperty verifyServerCertificate = new BooleanConnectionProperty( + "verifyServerCertificate", + true, + Messages.getString("ConnectionProperties.verifyServerCertificate"), + "5.1.6", SECURITY_CATEGORY, 4); + + private BooleanConnectionProperty useAffectedRows = new BooleanConnectionProperty("useAffectedRows", + false, + Messages.getString("ConnectionProperties.useAffectedRows"), + "5.1.7", MISC_CATEGORY, Integer.MIN_VALUE); + + private StringConnectionProperty passwordCharacterEncoding = new StringConnectionProperty("passwordCharacterEncoding", + null, + Messages.getString("ConnectionProperties.passwordCharacterEncoding"), + "5.1.7", SECURITY_CATEGORY, Integer.MIN_VALUE); + + private IntegerConnectionProperty maxAllowedPacket = new IntegerConnectionProperty("maxAllowedPacket", + -1, Messages.getString("ConnectionProperties.maxAllowedPacket"), "5.1.8", NETWORK_CATEGORY, + Integer.MIN_VALUE); + + private StringConnectionProperty authenticationPlugins = new StringConnectionProperty( + "authenticationPlugins", + null, + Messages.getString("ConnectionProperties.authenticationPlugins"), + "5.1.19", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); + + private StringConnectionProperty disabledAuthenticationPlugins = new StringConnectionProperty( + "disabledAuthenticationPlugins", + null, + Messages.getString("ConnectionProperties.disabledAuthenticationPlugins"), + "5.1.19", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); + + private StringConnectionProperty defaultAuthenticationPlugin = new StringConnectionProperty( + "defaultAuthenticationPlugin", + "com.mysql.jdbc.authentication.MysqlNativePasswordPlugin", + Messages.getString("ConnectionProperties.defaultAuthenticationPlugin"), + "5.1.19", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty disconnectOnExpiredPasswords = new BooleanConnectionProperty("disconnectOnExpiredPasswords", + true, + Messages.getString("ConnectionProperties.disconnectOnExpiredPasswords"), + "5.1.23", CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty getProceduresReturnsFunctions = new BooleanConnectionProperty( + "getProceduresReturnsFunctions", true, + Messages.getString("ConnectionProperties.getProceduresReturnsFunctions"), + "5.1.26", MISC_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty detectCustomCollations = new BooleanConnectionProperty( + "detectCustomCollations", false, + Messages.getString("ConnectionProperties.detectCustomCollations"), + "5.1.29", MISC_CATEGORY, Integer.MIN_VALUE); + + private StringConnectionProperty serverRSAPublicKeyFile = new StringConnectionProperty( + "serverRSAPublicKeyFile", null, //$NON-NLS-1$ + Messages.getString("ConnectionProperties.serverRSAPublicKeyFile"), "5.1.31", + SECURITY_CATEGORY, Integer.MIN_VALUE); + + private BooleanConnectionProperty allowPublicKeyRetrieval = new BooleanConnectionProperty( + "allowPublicKeyRetrieval", false, + Messages.getString("ConnectionProperties.allowPublicKeyRetrieval"), "5.1.31", + SECURITY_CATEGORY, Integer.MIN_VALUE); + + protected DriverPropertyInfo[] exposeAsDriverPropertyInfoInternal( + Properties info, int slotsToReserve) throws SQLException { + initializeProperties(info); + + int numProperties = PROPERTY_LIST.size(); + + int listSize = numProperties + slotsToReserve; + + DriverPropertyInfo[] driverProperties = new DriverPropertyInfo[listSize]; + + for (int i = slotsToReserve; i < listSize; i++) { + java.lang.reflect.Field propertyField = PROPERTY_LIST + .get(i - slotsToReserve); + + try { + ConnectionProperty propToExpose = (ConnectionProperty) propertyField + .get(this); + + if (info != null) { + propToExpose.initializeFrom(info, getExceptionInterceptor()); + } + + + driverProperties[i] = propToExpose.getAsDriverPropertyInfo(); + } catch (IllegalAccessException iae) { + throw SQLError.createSQLException(Messages.getString("ConnectionProperties.InternalPropertiesFailure"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + return driverProperties; + } + + protected Properties exposeAsProperties(Properties info) + throws SQLException { + if (info == null) { + info = new Properties(); + } + + int numPropertiesToSet = PROPERTY_LIST.size(); + + for (int i = 0; i < numPropertiesToSet; i++) { + java.lang.reflect.Field propertyField = PROPERTY_LIST + .get(i); + + try { + ConnectionProperty propToGet = (ConnectionProperty) propertyField + .get(this); + + Object propValue = propToGet.getValueAsObject(); + + if (propValue != null) { + info.setProperty(propToGet.getPropertyName(), propValue + .toString()); + } + } catch (IllegalAccessException iae) { + throw SQLError.createSQLException("Internal properties failure", //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + return info; + } + + class XmlMap { + protected Map> ordered = new TreeMap>(); + protected Map alpha = new TreeMap(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#exposeAsXml() + */ + public String exposeAsXml() throws SQLException { + StringBuffer xmlBuf = new StringBuffer(); + xmlBuf.append(""); //$NON-NLS-1$ + + int numPropertiesToSet = PROPERTY_LIST.size(); + + int numCategories = PROPERTY_CATEGORIES.length; + + Map propertyListByCategory = new HashMap(); + + for (int i = 0; i < numCategories; i++) { + propertyListByCategory.put(PROPERTY_CATEGORIES[i], new XmlMap()); + } + + // + // The following properties are not exposed as 'normal' properties, but + // they are + // settable nonetheless, so we need to have them documented, make sure + // that they sort 'first' as #1 and #2 in the category + // + StringConnectionProperty userProp = new StringConnectionProperty( + NonRegisteringDriver.USER_PROPERTY_KEY, null, + Messages.getString("ConnectionProperties.Username"), Messages.getString("ConnectionProperties.allVersions"), CONNECTION_AND_AUTH_CATEGORY, //$NON-NLS-1$ //$NON-NLS-2$ + Integer.MIN_VALUE + 1); + StringConnectionProperty passwordProp = new StringConnectionProperty( + NonRegisteringDriver.PASSWORD_PROPERTY_KEY, null, + Messages.getString("ConnectionProperties.Password"), Messages.getString("ConnectionProperties.allVersions"), //$NON-NLS-1$ //$NON-NLS-2$ + CONNECTION_AND_AUTH_CATEGORY, Integer.MIN_VALUE + 2); + + XmlMap connectionSortMaps = propertyListByCategory.get(CONNECTION_AND_AUTH_CATEGORY); + TreeMap userMap = new TreeMap(); + userMap.put(userProp.getPropertyName(), userProp); + + connectionSortMaps.ordered.put(Integer.valueOf(userProp.getOrder()), userMap); + + TreeMap passwordMap = new TreeMap(); + passwordMap.put(passwordProp.getPropertyName(), passwordProp); + + connectionSortMaps.ordered.put(new Integer(passwordProp.getOrder()), passwordMap); + + try { + for (int i = 0; i < numPropertiesToSet; i++) { + java.lang.reflect.Field propertyField = PROPERTY_LIST + .get(i); + ConnectionProperty propToGet = (ConnectionProperty) propertyField + .get(this); + XmlMap sortMaps = propertyListByCategory.get(propToGet + .getCategoryName()); + int orderInCategory = propToGet.getOrder(); + + if (orderInCategory == Integer.MIN_VALUE) { + sortMaps.alpha.put(propToGet.getPropertyName(), propToGet); + } else { + Integer order = Integer.valueOf(orderInCategory); + Map orderMap = sortMaps.ordered.get(order); + + if (orderMap == null) { + orderMap = new TreeMap(); + sortMaps.ordered.put(order, orderMap); + } + + orderMap.put(propToGet.getPropertyName(), propToGet); + } + } + + for (int j = 0; j < numCategories; j++) { + XmlMap sortMaps = propertyListByCategory.get(PROPERTY_CATEGORIES[j]); + + xmlBuf.append("\n "); //$NON-NLS-1$ + + for (Map orderedEl : sortMaps.ordered.values()) { + for (ConnectionProperty propToGet : orderedEl.values()) { + xmlBuf.append("\n \n"); //$NON-NLS-1$ + xmlBuf.append(" "); //$NON-NLS-1$ + String escapedDescription = propToGet.description; + escapedDescription = escapedDescription.replace("&", "&").replace("<", "<").replace(">", ">"); + + xmlBuf.append(escapedDescription); + xmlBuf.append("\n "); //$NON-NLS-1$ + } + } + + for (ConnectionProperty propToGet : sortMaps.alpha.values()) { + xmlBuf.append("\n \n"); //$NON-NLS-1$ + xmlBuf.append(" "); //$NON-NLS-1$ + xmlBuf.append(propToGet.description); + xmlBuf.append("\n "); //$NON-NLS-1$ + } + + xmlBuf.append("\n "); //$NON-NLS-1$ + } + } catch (IllegalAccessException iae) { + throw SQLError.createSQLException("Internal properties failure", //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + + xmlBuf.append("\n"); //$NON-NLS-1$ + + return xmlBuf.toString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAllowLoadLocalInfile() + */ + public boolean getAllowLoadLocalInfile() { + return this.allowLoadLocalInfile.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAllowMultiQueries() + */ + public boolean getAllowMultiQueries() { + return this.allowMultiQueries.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAllowNanAndInf() + */ + public boolean getAllowNanAndInf() { + return allowNanAndInf.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAllowUrlInLocalInfile() + */ + public boolean getAllowUrlInLocalInfile() { + return this.allowUrlInLocalInfile.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAlwaysSendSetIsolation() + */ + public boolean getAlwaysSendSetIsolation() { + return this.alwaysSendSetIsolation.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAutoDeserialize() + */ + public boolean getAutoDeserialize() { + return autoDeserialize.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAutoGenerateTestcaseScript() + */ + public boolean getAutoGenerateTestcaseScript() { + return this.autoGenerateTestcaseScriptAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAutoReconnectForPools() + */ + public boolean getAutoReconnectForPools() { + return this.autoReconnectForPoolsAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getBlobSendChunkSize() + */ + public int getBlobSendChunkSize() { + return blobSendChunkSize.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCacheCallableStatements() + */ + public boolean getCacheCallableStatements() { + return this.cacheCallableStatements.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCachePreparedStatements() + */ + public boolean getCachePreparedStatements() { + return ((Boolean) this.cachePreparedStatements.getValueAsObject()) + .booleanValue(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCacheResultSetMetadata() + */ + public boolean getCacheResultSetMetadata() { + return this.cacheResultSetMetaDataAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCacheServerConfiguration() + */ + public boolean getCacheServerConfiguration() { + return cacheServerConfiguration.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCallableStatementCacheSize() + */ + public int getCallableStatementCacheSize() { + return this.callableStatementCacheSize.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCapitalizeTypeNames() + */ + public boolean getCapitalizeTypeNames() { + return this.capitalizeTypeNames.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCharacterSetResults() + */ + public String getCharacterSetResults() { + return this.characterSetResults.getValueAsString(); + } + + public String getConnectionAttributes() { + return this.connectionAttributes.getValueAsString(); + } + + public void setConnectionAttributes(String val) { + this.connectionAttributes.setValue(val); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getClobberStreamingResults() + */ + public boolean getClobberStreamingResults() { + return this.clobberStreamingResults.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getClobCharacterEncoding() + */ + public String getClobCharacterEncoding() { + return this.clobCharacterEncoding.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getConnectionCollation() + */ + public String getConnectionCollation() { + return this.connectionCollation.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getConnectTimeout() + */ + public int getConnectTimeout() { + return this.connectTimeout.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getContinueBatchOnError() + */ + public boolean getContinueBatchOnError() { + return this.continueBatchOnError.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCreateDatabaseIfNotExist() + */ + public boolean getCreateDatabaseIfNotExist() { + return this.createDatabaseIfNotExist.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getDefaultFetchSize() + */ + public int getDefaultFetchSize() { + return this.defaultFetchSize.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getDontTrackOpenResources() + */ + public boolean getDontTrackOpenResources() { + return this.dontTrackOpenResources.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getDumpQueriesOnException() + */ + public boolean getDumpQueriesOnException() { + return this.dumpQueriesOnException.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getDynamicCalendars() + */ + public boolean getDynamicCalendars() { + return this.dynamicCalendars.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getElideSetAutoCommits() + */ + public boolean getElideSetAutoCommits() { + return this.elideSetAutoCommits.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getEmptyStringsConvertToZero() + */ + public boolean getEmptyStringsConvertToZero() { + return this.emptyStringsConvertToZero.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getEmulateLocators() + */ + public boolean getEmulateLocators() { + return this.emulateLocators.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getEmulateUnsupportedPstmts() + */ + public boolean getEmulateUnsupportedPstmts() { + return this.emulateUnsupportedPstmts.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getEnablePacketDebug() + */ + public boolean getEnablePacketDebug() { + return this.enablePacketDebug.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getEncoding() + */ + public String getEncoding() { + return this.characterEncodingAsString; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getExplainSlowQueries() + */ + public boolean getExplainSlowQueries() { + return this.explainSlowQueries.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getFailOverReadOnly() + */ + public boolean getFailOverReadOnly() { + return this.failOverReadOnly.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getGatherPerformanceMetrics() + */ + public boolean getGatherPerformanceMetrics() { + return this.gatherPerformanceMetrics.getValueAsBoolean(); + } + + /** + * DOCUMENT ME! + * + * @return + */ + protected boolean getHighAvailability() { + return this.highAvailabilityAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getHoldResultsOpenOverStatementClose() + */ + public boolean getHoldResultsOpenOverStatementClose() { + return holdResultsOpenOverStatementClose.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getIgnoreNonTxTables() + */ + public boolean getIgnoreNonTxTables() { + return this.ignoreNonTxTables.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getInitialTimeout() + */ + public int getInitialTimeout() { + return this.initialTimeout.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getInteractiveClient() + */ + public boolean getInteractiveClient() { + return this.isInteractiveClient.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getIsInteractiveClient() + */ + public boolean getIsInteractiveClient() { + return this.isInteractiveClient.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getJdbcCompliantTruncation() + */ + public boolean getJdbcCompliantTruncation() { + return this.jdbcCompliantTruncation.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getLocatorFetchBufferSize() + */ + public int getLocatorFetchBufferSize() { + return this.locatorFetchBufferSize.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getLogger() + */ + public String getLogger() { + return this.loggerClassName.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getLoggerClassName() + */ + public String getLoggerClassName() { + return this.loggerClassName.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getLogSlowQueries() + */ + public boolean getLogSlowQueries() { + return this.logSlowQueries.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getMaintainTimeStats() + */ + public boolean getMaintainTimeStats() { + return maintainTimeStatsAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getMaxQuerySizeToLog() + */ + public int getMaxQuerySizeToLog() { + return this.maxQuerySizeToLog.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getMaxReconnects() + */ + public int getMaxReconnects() { + return this.maxReconnects.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getMaxRows() + */ + public int getMaxRows() { + return this.maxRowsAsInt; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getMetadataCacheSize() + */ + public int getMetadataCacheSize() { + return this.metadataCacheSize.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getNoDatetimeStringSync() + */ + public boolean getNoDatetimeStringSync() { + return this.noDatetimeStringSync.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getNullCatalogMeansCurrent() + */ + public boolean getNullCatalogMeansCurrent() { + return this.nullCatalogMeansCurrent.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getNullNamePatternMatchesAll() + */ + public boolean getNullNamePatternMatchesAll() { + return this.nullNamePatternMatchesAll.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPacketDebugBufferSize() + */ + public int getPacketDebugBufferSize() { + return this.packetDebugBufferSize.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getParanoid() + */ + public boolean getParanoid() { + return this.paranoid.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPedantic() + */ + public boolean getPedantic() { + return this.pedantic.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPreparedStatementCacheSize() + */ + public int getPreparedStatementCacheSize() { + return ((Integer) this.preparedStatementCacheSize.getValueAsObject()) + .intValue(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPreparedStatementCacheSqlLimit() + */ + public int getPreparedStatementCacheSqlLimit() { + return ((Integer) this.preparedStatementCacheSqlLimit + .getValueAsObject()).intValue(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getProfileSql() + */ + public boolean getProfileSql() { + return this.profileSQLAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getProfileSQL() + */ + public boolean getProfileSQL() { + return this.profileSQL.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPropertiesTransform() + */ + public String getPropertiesTransform() { + return this.propertiesTransform.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getQueriesBeforeRetryMaster() + */ + public int getQueriesBeforeRetryMaster() { + return this.queriesBeforeRetryMaster.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getReconnectAtTxEnd() + */ + public boolean getReconnectAtTxEnd() { + return this.reconnectTxAtEndAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getRelaxAutoCommit() + */ + public boolean getRelaxAutoCommit() { + return this.relaxAutoCommit.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getReportMetricsIntervalMillis() + */ + public int getReportMetricsIntervalMillis() { + return this.reportMetricsIntervalMillis.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getRequireSSL() + */ + public boolean getRequireSSL() { + return this.requireSSL.getValueAsBoolean(); + } + + public boolean getRetainStatementAfterResultSetClose() { + return this.retainStatementAfterResultSetClose.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getRollbackOnPooledClose() + */ + public boolean getRollbackOnPooledClose() { + return this.rollbackOnPooledClose.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getRoundRobinLoadBalance() + */ + public boolean getRoundRobinLoadBalance() { + return this.roundRobinLoadBalance.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getRunningCTS13() + */ + public boolean getRunningCTS13() { + return this.runningCTS13.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getSecondsBeforeRetryMaster() + */ + public int getSecondsBeforeRetryMaster() { + return this.secondsBeforeRetryMaster.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getServerTimezone() + */ + public String getServerTimezone() { + return this.serverTimezone.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getSessionVariables() + */ + public String getSessionVariables() { + return sessionVariables.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getSlowQueryThresholdMillis() + */ + public int getSlowQueryThresholdMillis() { + return this.slowQueryThresholdMillis.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getSocketFactoryClassName() + */ + public String getSocketFactoryClassName() { + return this.socketFactoryClassName.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getSocketTimeout() + */ + public int getSocketTimeout() { + return this.socketTimeout.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getStrictFloatingPoint() + */ + public boolean getStrictFloatingPoint() { + return this.strictFloatingPoint.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getStrictUpdates() + */ + public boolean getStrictUpdates() { + return this.strictUpdates.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTinyInt1isBit() + */ + public boolean getTinyInt1isBit() { + return this.tinyInt1isBit.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTraceProtocol() + */ + public boolean getTraceProtocol() { + return this.traceProtocol.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTransformedBitIsBoolean() + */ + public boolean getTransformedBitIsBoolean() { + return this.transformedBitIsBoolean.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseCompression() + */ + public boolean getUseCompression() { + return this.useCompression.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseFastIntParsing() + */ + public boolean getUseFastIntParsing() { + return this.useFastIntParsing.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseHostsInPrivileges() + */ + public boolean getUseHostsInPrivileges() { + return this.useHostsInPrivileges.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseInformationSchema() + */ + public boolean getUseInformationSchema() { + return this.useInformationSchema.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseLocalSessionState() + */ + public boolean getUseLocalSessionState() { + return this.useLocalSessionState.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseOldUTF8Behavior() + */ + public boolean getUseOldUTF8Behavior() { + return this.useOldUTF8BehaviorAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseOnlyServerErrorMessages() + */ + public boolean getUseOnlyServerErrorMessages() { + return this.useOnlyServerErrorMessages.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseReadAheadInput() + */ + public boolean getUseReadAheadInput() { + return this.useReadAheadInput.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseServerPreparedStmts() + */ + public boolean getUseServerPreparedStmts() { + return this.detectServerPreparedStmts.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseSqlStateCodes() + */ + public boolean getUseSqlStateCodes() { + return this.useSqlStateCodes.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseSSL() + */ + public boolean getUseSSL() { + return this.useSSL.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseStreamLengthsInPrepStmts() + */ + public boolean getUseStreamLengthsInPrepStmts() { + return this.useStreamLengthsInPrepStmts.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseTimezone() + */ + public boolean getUseTimezone() { + return this.useTimezone.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseUltraDevWorkAround() + */ + public boolean getUseUltraDevWorkAround() { + return this.useUltraDevWorkAround.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseUnbufferedInput() + */ + public boolean getUseUnbufferedInput() { + return this.useUnbufferedInput.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseUnicode() + */ + public boolean getUseUnicode() { + return this.useUnicodeAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseUsageAdvisor() + */ + public boolean getUseUsageAdvisor() { + return this.useUsageAdvisorAsBoolean; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getYearIsDateType() + */ + public boolean getYearIsDateType() { + return this.yearIsDateType.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getZeroDateTimeBehavior() + */ + public String getZeroDateTimeBehavior() { + return this.zeroDateTimeBehavior.getValueAsString(); + } + + /** + * Initializes driver properties that come from a JNDI reference (in the + * case of a javax.sql.DataSource bound into some name service that doesn't + * handle Java objects directly). + * + * @param ref + * The JNDI Reference that holds RefAddrs for all properties + * @throws SQLException + * DOCUMENT ME! + */ + protected void initializeFromRef(Reference ref) throws SQLException { + int numPropertiesToSet = PROPERTY_LIST.size(); + + for (int i = 0; i < numPropertiesToSet; i++) { + java.lang.reflect.Field propertyField = PROPERTY_LIST + .get(i); + + try { + ConnectionProperty propToSet = (ConnectionProperty) propertyField + .get(this); + + if (ref != null) { + propToSet.initializeFrom(ref, getExceptionInterceptor()); + } + } catch (IllegalAccessException iae) { + throw SQLError.createSQLException("Internal properties failure", //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + postInitialization(); + } + + /** + * Initializes driver properties that come from URL or properties passed to + * the driver manager. + * + * @param info + * DOCUMENT ME! + * @throws SQLException + * DOCUMENT ME! + */ + protected void initializeProperties(Properties info) throws SQLException { + if (info != null) { + // For backwards-compatibility + String profileSqlLc = info.getProperty("profileSql"); //$NON-NLS-1$ + + if (profileSqlLc != null) { + info.put("profileSQL", profileSqlLc); //$NON-NLS-1$ + } + + Properties infoCopy = (Properties) info.clone(); + + infoCopy.remove(NonRegisteringDriver.HOST_PROPERTY_KEY); + infoCopy.remove(NonRegisteringDriver.USER_PROPERTY_KEY); + infoCopy.remove(NonRegisteringDriver.PASSWORD_PROPERTY_KEY); + infoCopy.remove(NonRegisteringDriver.DBNAME_PROPERTY_KEY); + infoCopy.remove(NonRegisteringDriver.PORT_PROPERTY_KEY); + infoCopy.remove("profileSql"); //$NON-NLS-1$ + + int numPropertiesToSet = PROPERTY_LIST.size(); + + for (int i = 0; i < numPropertiesToSet; i++) { + java.lang.reflect.Field propertyField = PROPERTY_LIST + .get(i); + + try { + ConnectionProperty propToSet = (ConnectionProperty) propertyField + .get(this); + + propToSet.initializeFrom(infoCopy, getExceptionInterceptor()); + } catch (IllegalAccessException iae) { + throw SQLError.createSQLException( + Messages.getString("ConnectionProperties.unableToInitDriverProperties") //$NON-NLS-1$ + + iae.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + postInitialization(); + } + } + + protected void postInitialization() throws SQLException { + + // Support 'old' profileSql capitalization + if (this.profileSql.getValueAsObject() != null) { + this.profileSQL.initializeFrom(this.profileSql.getValueAsObject() + .toString(), getExceptionInterceptor()); + } + + this.reconnectTxAtEndAsBoolean = ((Boolean) this.reconnectAtTxEnd + .getValueAsObject()).booleanValue(); + + // Adjust max rows + if (this.getMaxRows() == 0) { + // adjust so that it will become MysqlDefs.MAX_ROWS + // in execSQL() + this.maxRows.setValueAsObject(Integer.valueOf(-1)); + } + + // + // Check character encoding + // + String testEncoding = this.getEncoding(); + + if (testEncoding != null) { + // Attempt to use the encoding, and bail out if it + // can't be used + try { + String testString = "abc"; //$NON-NLS-1$ + StringUtils.getBytes(testString, testEncoding); + } catch (UnsupportedEncodingException UE) { + throw SQLError.createSQLException(Messages.getString( + "ConnectionProperties.unsupportedCharacterEncoding", + new Object[] {testEncoding}), "0S100", getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + // Metadata caching is only supported on JDK-1.4 and newer + // because it relies on LinkedHashMap being present. + // Check (and disable) if not supported + if (((Boolean) this.cacheResultSetMetadata.getValueAsObject()) + .booleanValue()) { + try { + Class.forName("java.util.LinkedHashMap"); //$NON-NLS-1$ + } catch (ClassNotFoundException cnfe) { + this.cacheResultSetMetadata.setValue(false); + } + } + + this.cacheResultSetMetaDataAsBoolean = this.cacheResultSetMetadata + .getValueAsBoolean(); + this.useUnicodeAsBoolean = this.useUnicode.getValueAsBoolean(); + this.characterEncodingAsString = ((String) this.characterEncoding + .getValueAsObject()); + this.characterEncodingIsAliasForSjis = CharsetMapping.isAliasForSjis(this.characterEncodingAsString); + this.highAvailabilityAsBoolean = this.autoReconnect.getValueAsBoolean(); + this.autoReconnectForPoolsAsBoolean = this.autoReconnectForPools + .getValueAsBoolean(); + this.maxRowsAsInt = ((Integer) this.maxRows.getValueAsObject()) + .intValue(); + this.profileSQLAsBoolean = this.profileSQL.getValueAsBoolean(); + this.useUsageAdvisorAsBoolean = this.useUsageAdvisor + .getValueAsBoolean(); + this.useOldUTF8BehaviorAsBoolean = this.useOldUTF8Behavior + .getValueAsBoolean(); + this.autoGenerateTestcaseScriptAsBoolean = this.autoGenerateTestcaseScript + .getValueAsBoolean(); + this.maintainTimeStatsAsBoolean = this.maintainTimeStats + .getValueAsBoolean(); + this.jdbcCompliantTruncationForReads = getJdbcCompliantTruncation(); + + if (getUseCursorFetch()) { + // assume they want to use server-side prepared statements + // because they're required for this functionality + setDetectServerPreparedStmts(true); + } + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAllowLoadLocalInfile(boolean) + */ + public void setAllowLoadLocalInfile(boolean property) { + this.allowLoadLocalInfile.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAllowMultiQueries(boolean) + */ + public void setAllowMultiQueries(boolean property) { + this.allowMultiQueries.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAllowNanAndInf(boolean) + */ + public void setAllowNanAndInf(boolean flag) { + this.allowNanAndInf.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAllowUrlInLocalInfile(boolean) + */ + public void setAllowUrlInLocalInfile(boolean flag) { + this.allowUrlInLocalInfile.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAlwaysSendSetIsolation(boolean) + */ + public void setAlwaysSendSetIsolation(boolean flag) { + this.alwaysSendSetIsolation.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAutoDeserialize(boolean) + */ + public void setAutoDeserialize(boolean flag) { + this.autoDeserialize.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAutoGenerateTestcaseScript(boolean) + */ + public void setAutoGenerateTestcaseScript(boolean flag) { + this.autoGenerateTestcaseScript.setValue(flag); + this.autoGenerateTestcaseScriptAsBoolean = this.autoGenerateTestcaseScript + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAutoReconnect(boolean) + */ + public void setAutoReconnect(boolean flag) { + this.autoReconnect.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAutoReconnectForConnectionPools(boolean) + */ + public void setAutoReconnectForConnectionPools(boolean property) { + this.autoReconnectForPools.setValue(property); + this.autoReconnectForPoolsAsBoolean = this.autoReconnectForPools + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAutoReconnectForPools(boolean) + */ + public void setAutoReconnectForPools(boolean flag) { + this.autoReconnectForPools.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setBlobSendChunkSize(java.lang.String) + */ + public void setBlobSendChunkSize(String value) throws SQLException { + this.blobSendChunkSize.setValue(value, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCacheCallableStatements(boolean) + */ + public void setCacheCallableStatements(boolean flag) { + this.cacheCallableStatements.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCachePreparedStatements(boolean) + */ + public void setCachePreparedStatements(boolean flag) { + this.cachePreparedStatements.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCacheResultSetMetadata(boolean) + */ + public void setCacheResultSetMetadata(boolean property) { + this.cacheResultSetMetadata.setValue(property); + this.cacheResultSetMetaDataAsBoolean = this.cacheResultSetMetadata + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCacheServerConfiguration(boolean) + */ + public void setCacheServerConfiguration(boolean flag) { + this.cacheServerConfiguration.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCallableStatementCacheSize(int) + */ + public void setCallableStatementCacheSize(int size) throws SQLException { + this.callableStatementCacheSize.setValue(size, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCapitalizeDBMDTypes(boolean) + */ + public void setCapitalizeDBMDTypes(boolean property) { + this.capitalizeTypeNames.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCapitalizeTypeNames(boolean) + */ + public void setCapitalizeTypeNames(boolean flag) { + this.capitalizeTypeNames.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCharacterEncoding(java.lang.String) + */ + public void setCharacterEncoding(String encoding) { + this.characterEncoding.setValue(encoding); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCharacterSetResults(java.lang.String) + */ + public void setCharacterSetResults(String characterSet) { + this.characterSetResults.setValue(characterSet); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setClobberStreamingResults(boolean) + */ + public void setClobberStreamingResults(boolean flag) { + this.clobberStreamingResults.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setClobCharacterEncoding(java.lang.String) + */ + public void setClobCharacterEncoding(String encoding) { + this.clobCharacterEncoding.setValue(encoding); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setConnectionCollation(java.lang.String) + */ + public void setConnectionCollation(String collation) { + this.connectionCollation.setValue(collation); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setConnectTimeout(int) + */ + public void setConnectTimeout(int timeoutMs) throws SQLException { + this.connectTimeout.setValue(timeoutMs, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setContinueBatchOnError(boolean) + */ + public void setContinueBatchOnError(boolean property) { + this.continueBatchOnError.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCreateDatabaseIfNotExist(boolean) + */ + public void setCreateDatabaseIfNotExist(boolean flag) { + this.createDatabaseIfNotExist.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setDefaultFetchSize(int) + */ + public void setDefaultFetchSize(int n) throws SQLException { + this.defaultFetchSize.setValue(n, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setDetectServerPreparedStmts(boolean) + */ + public void setDetectServerPreparedStmts(boolean property) { + this.detectServerPreparedStmts.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setDontTrackOpenResources(boolean) + */ + public void setDontTrackOpenResources(boolean flag) { + this.dontTrackOpenResources.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setDumpQueriesOnException(boolean) + */ + public void setDumpQueriesOnException(boolean flag) { + this.dumpQueriesOnException.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setDynamicCalendars(boolean) + */ + public void setDynamicCalendars(boolean flag) { + this.dynamicCalendars.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setElideSetAutoCommits(boolean) + */ + public void setElideSetAutoCommits(boolean flag) { + this.elideSetAutoCommits.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setEmptyStringsConvertToZero(boolean) + */ + public void setEmptyStringsConvertToZero(boolean flag) { + this.emptyStringsConvertToZero.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setEmulateLocators(boolean) + */ + public void setEmulateLocators(boolean property) { + this.emulateLocators.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setEmulateUnsupportedPstmts(boolean) + */ + public void setEmulateUnsupportedPstmts(boolean flag) { + this.emulateUnsupportedPstmts.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setEnablePacketDebug(boolean) + */ + public void setEnablePacketDebug(boolean flag) { + this.enablePacketDebug.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setEncoding(java.lang.String) + */ + public void setEncoding(String property) { + this.characterEncoding.setValue(property); + this.characterEncodingAsString = this.characterEncoding + .getValueAsString(); + this.characterEncodingIsAliasForSjis = CharsetMapping.isAliasForSjis(this.characterEncodingAsString); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setExplainSlowQueries(boolean) + */ + public void setExplainSlowQueries(boolean flag) { + this.explainSlowQueries.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setFailOverReadOnly(boolean) + */ + public void setFailOverReadOnly(boolean flag) { + this.failOverReadOnly.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setGatherPerformanceMetrics(boolean) + */ + public void setGatherPerformanceMetrics(boolean flag) { + this.gatherPerformanceMetrics.setValue(flag); + } + + /** + * DOCUMENT ME! + * + * @param property + */ + protected void setHighAvailability(boolean property) { + this.autoReconnect.setValue(property); + this.highAvailabilityAsBoolean = this.autoReconnect.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setHoldResultsOpenOverStatementClose(boolean) + */ + public void setHoldResultsOpenOverStatementClose(boolean flag) { + this.holdResultsOpenOverStatementClose.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setIgnoreNonTxTables(boolean) + */ + public void setIgnoreNonTxTables(boolean property) { + this.ignoreNonTxTables.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setInitialTimeout(int) + */ + public void setInitialTimeout(int property) throws SQLException { + this.initialTimeout.setValue(property, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setIsInteractiveClient(boolean) + */ + public void setIsInteractiveClient(boolean property) { + this.isInteractiveClient.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setJdbcCompliantTruncation(boolean) + */ + public void setJdbcCompliantTruncation(boolean flag) { + this.jdbcCompliantTruncation.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setLocatorFetchBufferSize(java.lang.String) + */ + public void setLocatorFetchBufferSize(String value) throws SQLException { + this.locatorFetchBufferSize.setValue(value, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setLogger(java.lang.String) + */ + public void setLogger(String property) { + this.loggerClassName.setValueAsObject(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setLoggerClassName(java.lang.String) + */ + public void setLoggerClassName(String className) { + this.loggerClassName.setValue(className); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setLogSlowQueries(boolean) + */ + public void setLogSlowQueries(boolean flag) { + this.logSlowQueries.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setMaintainTimeStats(boolean) + */ + public void setMaintainTimeStats(boolean flag) { + this.maintainTimeStats.setValue(flag); + this.maintainTimeStatsAsBoolean = this.maintainTimeStats + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setMaxQuerySizeToLog(int) + */ + public void setMaxQuerySizeToLog(int sizeInBytes) throws SQLException { + this.maxQuerySizeToLog.setValue(sizeInBytes, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setMaxReconnects(int) + */ + public void setMaxReconnects(int property) throws SQLException { + this.maxReconnects.setValue(property, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setMaxRows(int) + */ + public void setMaxRows(int property) throws SQLException { + this.maxRows.setValue(property, getExceptionInterceptor()); + this.maxRowsAsInt = this.maxRows.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setMetadataCacheSize(int) + */ + public void setMetadataCacheSize(int value) throws SQLException { + this.metadataCacheSize.setValue(value, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setNoDatetimeStringSync(boolean) + */ + public void setNoDatetimeStringSync(boolean flag) { + this.noDatetimeStringSync.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setNullCatalogMeansCurrent(boolean) + */ + public void setNullCatalogMeansCurrent(boolean value) { + this.nullCatalogMeansCurrent.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setNullNamePatternMatchesAll(boolean) + */ + public void setNullNamePatternMatchesAll(boolean value) { + this.nullNamePatternMatchesAll.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPacketDebugBufferSize(int) + */ + public void setPacketDebugBufferSize(int size) throws SQLException { + this.packetDebugBufferSize.setValue(size, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setParanoid(boolean) + */ + public void setParanoid(boolean property) { + this.paranoid.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPedantic(boolean) + */ + public void setPedantic(boolean property) { + this.pedantic.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPreparedStatementCacheSize(int) + */ + public void setPreparedStatementCacheSize(int cacheSize) throws SQLException { + this.preparedStatementCacheSize.setValue(cacheSize, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPreparedStatementCacheSqlLimit(int) + */ + public void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) throws SQLException { + this.preparedStatementCacheSqlLimit.setValue(cacheSqlLimit, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setProfileSql(boolean) + */ + public void setProfileSql(boolean property) { + this.profileSQL.setValue(property); + this.profileSQLAsBoolean = this.profileSQL.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setProfileSQL(boolean) + */ + public void setProfileSQL(boolean flag) { + this.profileSQL.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPropertiesTransform(java.lang.String) + */ + public void setPropertiesTransform(String value) { + this.propertiesTransform.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setQueriesBeforeRetryMaster(int) + */ + public void setQueriesBeforeRetryMaster(int property) throws SQLException { + this.queriesBeforeRetryMaster.setValue(property, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setReconnectAtTxEnd(boolean) + */ + public void setReconnectAtTxEnd(boolean property) { + this.reconnectAtTxEnd.setValue(property); + this.reconnectTxAtEndAsBoolean = this.reconnectAtTxEnd + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRelaxAutoCommit(boolean) + */ + public void setRelaxAutoCommit(boolean property) { + this.relaxAutoCommit.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setReportMetricsIntervalMillis(int) + */ + public void setReportMetricsIntervalMillis(int millis) throws SQLException { + this.reportMetricsIntervalMillis.setValue(millis, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRequireSSL(boolean) + */ + public void setRequireSSL(boolean property) { + this.requireSSL.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRetainStatementAfterResultSetClose(boolean) + */ + public void setRetainStatementAfterResultSetClose(boolean flag) { + this.retainStatementAfterResultSetClose.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRollbackOnPooledClose(boolean) + */ + public void setRollbackOnPooledClose(boolean flag) { + this.rollbackOnPooledClose.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRoundRobinLoadBalance(boolean) + */ + public void setRoundRobinLoadBalance(boolean flag) { + this.roundRobinLoadBalance.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRunningCTS13(boolean) + */ + public void setRunningCTS13(boolean flag) { + this.runningCTS13.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setSecondsBeforeRetryMaster(int) + */ + public void setSecondsBeforeRetryMaster(int property) throws SQLException { + this.secondsBeforeRetryMaster.setValue(property, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setServerTimezone(java.lang.String) + */ + public void setServerTimezone(String property) { + this.serverTimezone.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setSessionVariables(java.lang.String) + */ + public void setSessionVariables(String variables) { + this.sessionVariables.setValue(variables); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setSlowQueryThresholdMillis(int) + */ + public void setSlowQueryThresholdMillis(int millis) throws SQLException { + this.slowQueryThresholdMillis.setValue(millis, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setSocketFactoryClassName(java.lang.String) + */ + public void setSocketFactoryClassName(String property) { + this.socketFactoryClassName.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setSocketTimeout(int) + */ + public void setSocketTimeout(int property) throws SQLException { + this.socketTimeout.setValue(property, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setStrictFloatingPoint(boolean) + */ + public void setStrictFloatingPoint(boolean property) { + this.strictFloatingPoint.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setStrictUpdates(boolean) + */ + public void setStrictUpdates(boolean property) { + this.strictUpdates.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTinyInt1isBit(boolean) + */ + public void setTinyInt1isBit(boolean flag) { + this.tinyInt1isBit.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTraceProtocol(boolean) + */ + public void setTraceProtocol(boolean flag) { + this.traceProtocol.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTransformedBitIsBoolean(boolean) + */ + public void setTransformedBitIsBoolean(boolean flag) { + this.transformedBitIsBoolean.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseCompression(boolean) + */ + public void setUseCompression(boolean property) { + this.useCompression.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseFastIntParsing(boolean) + */ + public void setUseFastIntParsing(boolean flag) { + this.useFastIntParsing.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseHostsInPrivileges(boolean) + */ + public void setUseHostsInPrivileges(boolean property) { + this.useHostsInPrivileges.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseInformationSchema(boolean) + */ + public void setUseInformationSchema(boolean flag) { + this.useInformationSchema.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseLocalSessionState(boolean) + */ + public void setUseLocalSessionState(boolean flag) { + this.useLocalSessionState.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseOldUTF8Behavior(boolean) + */ + public void setUseOldUTF8Behavior(boolean flag) { + this.useOldUTF8Behavior.setValue(flag); + this.useOldUTF8BehaviorAsBoolean = this.useOldUTF8Behavior + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseOnlyServerErrorMessages(boolean) + */ + public void setUseOnlyServerErrorMessages(boolean flag) { + this.useOnlyServerErrorMessages.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseReadAheadInput(boolean) + */ + public void setUseReadAheadInput(boolean flag) { + this.useReadAheadInput.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseServerPreparedStmts(boolean) + */ + public void setUseServerPreparedStmts(boolean flag) { + this.detectServerPreparedStmts.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseSqlStateCodes(boolean) + */ + public void setUseSqlStateCodes(boolean flag) { + this.useSqlStateCodes.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseSSL(boolean) + */ + public void setUseSSL(boolean property) { + this.useSSL.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseStreamLengthsInPrepStmts(boolean) + */ + public void setUseStreamLengthsInPrepStmts(boolean property) { + this.useStreamLengthsInPrepStmts.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseTimezone(boolean) + */ + public void setUseTimezone(boolean property) { + this.useTimezone.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseUltraDevWorkAround(boolean) + */ + public void setUseUltraDevWorkAround(boolean property) { + this.useUltraDevWorkAround.setValue(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseUnbufferedInput(boolean) + */ + public void setUseUnbufferedInput(boolean flag) { + this.useUnbufferedInput.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseUnicode(boolean) + */ + public void setUseUnicode(boolean flag) { + this.useUnicode.setValue(flag); + this.useUnicodeAsBoolean = this.useUnicode.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseUsageAdvisor(boolean) + */ + public void setUseUsageAdvisor(boolean useUsageAdvisorFlag) { + this.useUsageAdvisor.setValue(useUsageAdvisorFlag); + this.useUsageAdvisorAsBoolean = this.useUsageAdvisor + .getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setYearIsDateType(boolean) + */ + public void setYearIsDateType(boolean flag) { + this.yearIsDateType.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setZeroDateTimeBehavior(java.lang.String) + */ + public void setZeroDateTimeBehavior(String behavior) { + this.zeroDateTimeBehavior.setValue(behavior); + } + + protected void storeToRef(Reference ref) throws SQLException { + int numPropertiesToSet = PROPERTY_LIST.size(); + + for (int i = 0; i < numPropertiesToSet; i++) { + java.lang.reflect.Field propertyField = PROPERTY_LIST + .get(i); + + try { + ConnectionProperty propToStore = (ConnectionProperty) propertyField + .get(this); + + if (ref != null) { + propToStore.storeTo(ref); + } + } catch (IllegalAccessException iae) { + throw SQLError.createSQLException(Messages.getString("ConnectionProperties.errorNotExpected"), getExceptionInterceptor()); //$NON-NLS-1$ + } + } + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#useUnbufferedInput() + */ + public boolean useUnbufferedInput() { + return this.useUnbufferedInput.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseCursorFetch() + */ + public boolean getUseCursorFetch() { + return this.useCursorFetch.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseCursorFetch(boolean) + */ + public void setUseCursorFetch(boolean flag) { + this.useCursorFetch.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getOverrideSupportsIntegrityEnhancementFacility() + */ + public boolean getOverrideSupportsIntegrityEnhancementFacility() { + return this.overrideSupportsIntegrityEnhancementFacility.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setOverrideSupportsIntegrityEnhancementFacility(boolean) + */ + public void setOverrideSupportsIntegrityEnhancementFacility(boolean flag) { + this.overrideSupportsIntegrityEnhancementFacility.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getNoTimezoneConversionForTimeType() + */ + public boolean getNoTimezoneConversionForTimeType() { + return this.noTimezoneConversionForTimeType.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setNoTimezoneConversionForTimeType(boolean) + */ + public void setNoTimezoneConversionForTimeType(boolean flag) { + this.noTimezoneConversionForTimeType.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseJDBCCompliantTimezoneShift() + */ + public boolean getUseJDBCCompliantTimezoneShift() { + return this.useJDBCCompliantTimezoneShift.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseJDBCCompliantTimezoneShift(boolean) + */ + public void setUseJDBCCompliantTimezoneShift(boolean flag) { + this.useJDBCCompliantTimezoneShift.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getAutoClosePStmtStreams() + */ + public boolean getAutoClosePStmtStreams() { + return this.autoClosePStmtStreams.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setAutoClosePStmtStreams(boolean) + */ + public void setAutoClosePStmtStreams(boolean flag) { + this.autoClosePStmtStreams.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getProcessEscapeCodesForPrepStmts() + */ + public boolean getProcessEscapeCodesForPrepStmts() { + return this.processEscapeCodesForPrepStmts.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setProcessEscapeCodesForPrepStmts(boolean) + */ + public void setProcessEscapeCodesForPrepStmts(boolean flag) { + this.processEscapeCodesForPrepStmts.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseGmtMillisForDatetimes() + */ + public boolean getUseGmtMillisForDatetimes() { + return this.useGmtMillisForDatetimes.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseGmtMillisForDatetimes(boolean) + */ + public void setUseGmtMillisForDatetimes(boolean flag) { + this.useGmtMillisForDatetimes.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getDumpMetadataOnColumnNotFound() + */ + public boolean getDumpMetadataOnColumnNotFound() { + return this.dumpMetadataOnColumnNotFound.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setDumpMetadataOnColumnNotFound(boolean) + */ + public void setDumpMetadataOnColumnNotFound(boolean flag) { + this.dumpMetadataOnColumnNotFound.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getResourceId() + */ + public String getResourceId() { + return this.resourceId.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setResourceId(java.lang.String) + */ + public void setResourceId(String resourceId) { + this.resourceId.setValue(resourceId); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getRewriteBatchedStatements() + */ + public boolean getRewriteBatchedStatements() { + return this.rewriteBatchedStatements.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setRewriteBatchedStatements(boolean) + */ + public void setRewriteBatchedStatements(boolean flag) { + this.rewriteBatchedStatements.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getJdbcCompliantTruncationForReads() + */ + public boolean getJdbcCompliantTruncationForReads() { + return this.jdbcCompliantTruncationForReads; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setJdbcCompliantTruncationForReads(boolean) + */ + public void setJdbcCompliantTruncationForReads( + boolean jdbcCompliantTruncationForReads) { + this.jdbcCompliantTruncationForReads = jdbcCompliantTruncationForReads; + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseJvmCharsetConverters() + */ + public boolean getUseJvmCharsetConverters() { + return this.useJvmCharsetConverters.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseJvmCharsetConverters(boolean) + */ + public void setUseJvmCharsetConverters(boolean flag) { + this.useJvmCharsetConverters.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPinGlobalTxToPhysicalConnection() + */ + public boolean getPinGlobalTxToPhysicalConnection() { + return this.pinGlobalTxToPhysicalConnection.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPinGlobalTxToPhysicalConnection(boolean) + */ + public void setPinGlobalTxToPhysicalConnection(boolean flag) { + this.pinGlobalTxToPhysicalConnection.setValue(flag); + } + + /* + * "Aliases" which match the property names to make using + * from datasources easier. + */ + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setGatherPerfMetrics(boolean) + */ + public void setGatherPerfMetrics(boolean flag) { + setGatherPerformanceMetrics(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getGatherPerfMetrics() + */ + public boolean getGatherPerfMetrics() { + return getGatherPerformanceMetrics(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUltraDevHack(boolean) + */ + public void setUltraDevHack(boolean flag) { + setUseUltraDevWorkAround(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUltraDevHack() + */ + public boolean getUltraDevHack() { + return getUseUltraDevWorkAround(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setInteractiveClient(boolean) + */ + public void setInteractiveClient(boolean property) { + setIsInteractiveClient(property); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setSocketFactory(java.lang.String) + */ + public void setSocketFactory(String name) { + setSocketFactoryClassName(name); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getSocketFactory() + */ + public String getSocketFactory() { + return getSocketFactoryClassName(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseServerPrepStmts(boolean) + */ + public void setUseServerPrepStmts(boolean flag) { + setUseServerPreparedStmts(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseServerPrepStmts() + */ + public boolean getUseServerPrepStmts() { + return getUseServerPreparedStmts(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCacheCallableStmts(boolean) + */ + public void setCacheCallableStmts(boolean flag) { + setCacheCallableStatements(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCacheCallableStmts() + */ + public boolean getCacheCallableStmts() { + return getCacheCallableStatements(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCachePrepStmts(boolean) + */ + public void setCachePrepStmts(boolean flag) { + setCachePreparedStatements(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCachePrepStmts() + */ + public boolean getCachePrepStmts() { + return getCachePreparedStatements(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setCallableStmtCacheSize(int) + */ + public void setCallableStmtCacheSize(int cacheSize) throws SQLException { + setCallableStatementCacheSize(cacheSize); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getCallableStmtCacheSize() + */ + public int getCallableStmtCacheSize() { + return getCallableStatementCacheSize(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPrepStmtCacheSize(int) + */ + public void setPrepStmtCacheSize(int cacheSize) throws SQLException { + setPreparedStatementCacheSize(cacheSize); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPrepStmtCacheSize() + */ + public int getPrepStmtCacheSize() { + return getPreparedStatementCacheSize(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPrepStmtCacheSqlLimit(int) + */ + public void setPrepStmtCacheSqlLimit(int sqlLimit) throws SQLException { + setPreparedStatementCacheSqlLimit(sqlLimit); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPrepStmtCacheSqlLimit() + */ + public int getPrepStmtCacheSqlLimit() { + return getPreparedStatementCacheSqlLimit(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getNoAccessToProcedureBodies() + */ + public boolean getNoAccessToProcedureBodies() { + return this.noAccessToProcedureBodies.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setNoAccessToProcedureBodies(boolean) + */ + public void setNoAccessToProcedureBodies(boolean flag) { + this.noAccessToProcedureBodies.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseOldAliasMetadataBehavior() + */ + public boolean getUseOldAliasMetadataBehavior() { + return this.useOldAliasMetadataBehavior.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseOldAliasMetadataBehavior(boolean) + */ + public void setUseOldAliasMetadataBehavior(boolean flag) { + this.useOldAliasMetadataBehavior.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getClientCertificateKeyStorePassword() + */ + public String getClientCertificateKeyStorePassword() { + return clientCertificateKeyStorePassword.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setClientCertificateKeyStorePassword(java.lang.String) + */ + public void setClientCertificateKeyStorePassword( + String value) { + this.clientCertificateKeyStorePassword.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getClientCertificateKeyStoreType() + */ + public String getClientCertificateKeyStoreType() { + return clientCertificateKeyStoreType.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setClientCertificateKeyStoreType(java.lang.String) + */ + public void setClientCertificateKeyStoreType( + String value) { + this.clientCertificateKeyStoreType.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getClientCertificateKeyStoreUrl() + */ + public String getClientCertificateKeyStoreUrl() { + return clientCertificateKeyStoreUrl.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setClientCertificateKeyStoreUrl(java.lang.String) + */ + public void setClientCertificateKeyStoreUrl( + String value) { + this.clientCertificateKeyStoreUrl.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTrustCertificateKeyStorePassword() + */ + public String getTrustCertificateKeyStorePassword() { + return trustCertificateKeyStorePassword.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTrustCertificateKeyStorePassword(java.lang.String) + */ + public void setTrustCertificateKeyStorePassword( + String value) { + this.trustCertificateKeyStorePassword.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTrustCertificateKeyStoreType() + */ + public String getTrustCertificateKeyStoreType() { + return trustCertificateKeyStoreType.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTrustCertificateKeyStoreType(java.lang.String) + */ + public void setTrustCertificateKeyStoreType( + String value) { + this.trustCertificateKeyStoreType.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTrustCertificateKeyStoreUrl() + */ + public String getTrustCertificateKeyStoreUrl() { + return trustCertificateKeyStoreUrl.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTrustCertificateKeyStoreUrl(java.lang.String) + */ + public void setTrustCertificateKeyStoreUrl( + String value) { + this.trustCertificateKeyStoreUrl.setValue(value); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseSSPSCompatibleTimezoneShift() + */ + public boolean getUseSSPSCompatibleTimezoneShift() { + return this.useSSPSCompatibleTimezoneShift.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseSSPSCompatibleTimezoneShift(boolean) + */ + public void setUseSSPSCompatibleTimezoneShift(boolean flag) { + this.useSSPSCompatibleTimezoneShift.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getTreatUtilDateAsTimestamp() + */ + public boolean getTreatUtilDateAsTimestamp() { + return this.treatUtilDateAsTimestamp.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setTreatUtilDateAsTimestamp(boolean) + */ + public void setTreatUtilDateAsTimestamp(boolean flag) { + this.treatUtilDateAsTimestamp.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseFastDateParsing() + */ + public boolean getUseFastDateParsing() { + return this.useFastDateParsing.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseFastDateParsing(boolean) + */ + public void setUseFastDateParsing(boolean flag) { + this.useFastDateParsing.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getLocalSocketAddress() + */ + public String getLocalSocketAddress() { + return this.localSocketAddress.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setLocalSocketAddress(java.lang.String) + */ + public void setLocalSocketAddress(String address) { + this.localSocketAddress.setValue(address); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseConfigs(java.lang.String) + */ + public void setUseConfigs(String configs) { + this.useConfigs.setValue(configs); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseConfigs() + */ + public String getUseConfigs() { + return this.useConfigs.getValueAsString(); + } + + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getGenerateSimpleParameterMetadata() + */ + public boolean getGenerateSimpleParameterMetadata() { + return this.generateSimpleParameterMetadata.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setGenerateSimpleParameterMetadata(boolean) + */ + public void setGenerateSimpleParameterMetadata(boolean flag) { + this.generateSimpleParameterMetadata.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getLogXaCommands() + */ + public boolean getLogXaCommands() { + return this.logXaCommands.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setLogXaCommands(boolean) + */ + public void setLogXaCommands(boolean flag) { + this.logXaCommands.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getResultSetSizeThreshold() + */ + public int getResultSetSizeThreshold() { + return this.resultSetSizeThreshold.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setResultSetSizeThreshold(int) + */ + public void setResultSetSizeThreshold(int threshold) throws SQLException { + this.resultSetSizeThreshold.setValue(threshold, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getNetTimeoutForStreamingResults() + */ + public int getNetTimeoutForStreamingResults() { + return this.netTimeoutForStreamingResults.getValueAsInt(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setNetTimeoutForStreamingResults(int) + */ + public void setNetTimeoutForStreamingResults(int value) throws SQLException { + this.netTimeoutForStreamingResults.setValue(value, getExceptionInterceptor()); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getEnableQueryTimeouts() + */ + public boolean getEnableQueryTimeouts() { + return this.enableQueryTimeouts.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setEnableQueryTimeouts(boolean) + */ + public void setEnableQueryTimeouts(boolean flag) { + this.enableQueryTimeouts.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getPadCharsWithSpace() + */ + public boolean getPadCharsWithSpace() { + return this.padCharsWithSpace.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setPadCharsWithSpace(boolean) + */ + public void setPadCharsWithSpace(boolean flag) { + this.padCharsWithSpace.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getUseDynamicCharsetInfo() + */ + public boolean getUseDynamicCharsetInfo() { + return this.useDynamicCharsetInfo.getValueAsBoolean(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setUseDynamicCharsetInfo(boolean) + */ + public void setUseDynamicCharsetInfo(boolean flag) { + this.useDynamicCharsetInfo.setValue(flag); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#getClientInfoProvider() + */ + public String getClientInfoProvider() { + return this.clientInfoProvider.getValueAsString(); + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.IConnectionProperties#setClientInfoProvider(java.lang.String) + */ + public void setClientInfoProvider(String classname) { + this.clientInfoProvider.setValue(classname); + } + + public boolean getPopulateInsertRowWithDefaultValues() { + return this.populateInsertRowWithDefaultValues.getValueAsBoolean(); + } + + public void setPopulateInsertRowWithDefaultValues(boolean flag) { + this.populateInsertRowWithDefaultValues.setValue(flag); + } + + public String getLoadBalanceStrategy() { + return this.loadBalanceStrategy.getValueAsString(); + } + + public void setLoadBalanceStrategy(String strategy) { + this.loadBalanceStrategy.setValue(strategy); + } + + public boolean getTcpNoDelay() { + return this.tcpNoDelay.getValueAsBoolean(); + } + + public void setTcpNoDelay(boolean flag) { + this.tcpNoDelay.setValue(flag); + } + + public boolean getTcpKeepAlive() { + return this.tcpKeepAlive.getValueAsBoolean(); + } + + public void setTcpKeepAlive(boolean flag) { + this.tcpKeepAlive.setValue(flag); + } + + public int getTcpRcvBuf() { + return this.tcpRcvBuf.getValueAsInt(); + } + + public void setTcpRcvBuf(int bufSize) throws SQLException { + this.tcpRcvBuf.setValue(bufSize, getExceptionInterceptor()); + } + + public int getTcpSndBuf() { + return this.tcpSndBuf.getValueAsInt(); + } + + public void setTcpSndBuf(int bufSize) throws SQLException { + this.tcpSndBuf.setValue(bufSize, getExceptionInterceptor()); + } + + public int getTcpTrafficClass() { + return this.tcpTrafficClass.getValueAsInt(); + } + + public void setTcpTrafficClass(int classFlags) throws SQLException { + this.tcpTrafficClass.setValue(classFlags, getExceptionInterceptor()); + } + + public boolean getUseNanosForElapsedTime() { + return this.useNanosForElapsedTime.getValueAsBoolean(); + } + + public void setUseNanosForElapsedTime(boolean flag) { + this.useNanosForElapsedTime.setValue(flag); + } + + public long getSlowQueryThresholdNanos() { + return this.slowQueryThresholdNanos.getValueAsLong(); + } + + public void setSlowQueryThresholdNanos(long nanos) throws SQLException { + this.slowQueryThresholdNanos.setValue(nanos, getExceptionInterceptor()); + } + + public String getStatementInterceptors() { + return this.statementInterceptors.getValueAsString(); + } + + public void setStatementInterceptors(String value) { + this.statementInterceptors.setValue(value); + } + + public boolean getUseDirectRowUnpack() { + return this.useDirectRowUnpack.getValueAsBoolean(); + } + + public void setUseDirectRowUnpack(boolean flag) { + this.useDirectRowUnpack.setValue(flag); + } + + public String getLargeRowSizeThreshold() { + return this.largeRowSizeThreshold.getValueAsString(); + } + + public void setLargeRowSizeThreshold(String value) throws SQLException { + this.largeRowSizeThreshold.setValue(value, getExceptionInterceptor()); + } + + public boolean getUseBlobToStoreUTF8OutsideBMP() { + return this.useBlobToStoreUTF8OutsideBMP.getValueAsBoolean(); + } + + public void setUseBlobToStoreUTF8OutsideBMP(boolean flag) { + this.useBlobToStoreUTF8OutsideBMP.setValue(flag); + } + + public String getUtf8OutsideBmpExcludedColumnNamePattern() { + return this.utf8OutsideBmpExcludedColumnNamePattern.getValueAsString(); + } + + public void setUtf8OutsideBmpExcludedColumnNamePattern(String regexPattern) { + this.utf8OutsideBmpExcludedColumnNamePattern.setValue(regexPattern); + } + + public String getUtf8OutsideBmpIncludedColumnNamePattern() { + return this.utf8OutsideBmpIncludedColumnNamePattern.getValueAsString(); + } + + public void setUtf8OutsideBmpIncludedColumnNamePattern(String regexPattern) { + this.utf8OutsideBmpIncludedColumnNamePattern.setValue(regexPattern); + } + + public boolean getIncludeInnodbStatusInDeadlockExceptions() { + return this.includeInnodbStatusInDeadlockExceptions.getValueAsBoolean(); + } + + public void setIncludeInnodbStatusInDeadlockExceptions(boolean flag) { + this.includeInnodbStatusInDeadlockExceptions.setValue(flag); + } + + public boolean getBlobsAreStrings() { + return this.blobsAreStrings.getValueAsBoolean(); + } + + public void setBlobsAreStrings(boolean flag) { + this.blobsAreStrings.setValue(flag); + } + + public boolean getFunctionsNeverReturnBlobs() { + return this.functionsNeverReturnBlobs.getValueAsBoolean(); + } + + public void setFunctionsNeverReturnBlobs(boolean flag) { + this.functionsNeverReturnBlobs.setValue(flag); + } + + public boolean getAutoSlowLog() { + return this.autoSlowLog.getValueAsBoolean(); + } + + public void setAutoSlowLog(boolean flag) { + this.autoSlowLog.setValue(flag); + } + + public String getConnectionLifecycleInterceptors() { + return this.connectionLifecycleInterceptors.getValueAsString(); + } + + public void setConnectionLifecycleInterceptors(String interceptors) { + this.connectionLifecycleInterceptors.setValue(interceptors); + } + + public String getProfilerEventHandler() { + return this.profilerEventHandler.getValueAsString(); + } + + public void setProfilerEventHandler(String handler) { + this.profilerEventHandler.setValue(handler); + } + + public boolean getVerifyServerCertificate() { + return this.verifyServerCertificate.getValueAsBoolean(); + } + + public void setVerifyServerCertificate(boolean flag) { + this.verifyServerCertificate.setValue(flag); + } + + public boolean getUseLegacyDatetimeCode() { + return this.useLegacyDatetimeCode.getValueAsBoolean(); + } + + public void setUseLegacyDatetimeCode(boolean flag) { + this.useLegacyDatetimeCode.setValue(flag); + } + + public int getSelfDestructOnPingSecondsLifetime() { + return this.selfDestructOnPingSecondsLifetime.getValueAsInt(); + } + + public void setSelfDestructOnPingSecondsLifetime(int seconds) throws SQLException { + this.selfDestructOnPingSecondsLifetime.setValue(seconds, getExceptionInterceptor()); + } + + public int getSelfDestructOnPingMaxOperations() { + return this.selfDestructOnPingMaxOperations.getValueAsInt(); + } + + public void setSelfDestructOnPingMaxOperations(int maxOperations) throws SQLException { + this.selfDestructOnPingMaxOperations.setValue(maxOperations, getExceptionInterceptor()); + } + + public boolean getUseColumnNamesInFindColumn() { + return this.useColumnNamesInFindColumn.getValueAsBoolean(); + } + + public void setUseColumnNamesInFindColumn(boolean flag) { + this.useColumnNamesInFindColumn.setValue(flag); + } + + public boolean getUseLocalTransactionState() { + return this.useLocalTransactionState.getValueAsBoolean(); + } + + public void setUseLocalTransactionState(boolean flag) { + this.useLocalTransactionState.setValue(flag); + } + + public boolean getCompensateOnDuplicateKeyUpdateCounts() { + return this.compensateOnDuplicateKeyUpdateCounts.getValueAsBoolean(); + } + + public void setCompensateOnDuplicateKeyUpdateCounts(boolean flag) { + this.compensateOnDuplicateKeyUpdateCounts.setValue(flag); + } + + public int getLoadBalanceBlacklistTimeout() { + return loadBalanceBlacklistTimeout.getValueAsInt(); + } + + public void setLoadBalanceBlacklistTimeout(int loadBalanceBlacklistTimeout) throws SQLException { + this.loadBalanceBlacklistTimeout.setValue(loadBalanceBlacklistTimeout, getExceptionInterceptor()); + } + + public int getLoadBalancePingTimeout() { + return loadBalancePingTimeout.getValueAsInt(); + } + + public void setLoadBalancePingTimeout(int loadBalancePingTimeout) throws SQLException { + this.loadBalancePingTimeout.setValue(loadBalancePingTimeout, getExceptionInterceptor()); + } + + public void setRetriesAllDown(int retriesAllDown) throws SQLException { + this.retriesAllDown.setValue(retriesAllDown, getExceptionInterceptor()); + } + + public int getRetriesAllDown() { + return this.retriesAllDown.getValueAsInt(); + } + + public void setUseAffectedRows(boolean flag) { + this.useAffectedRows.setValue(flag); + } + + public boolean getUseAffectedRows() { + return this.useAffectedRows.getValueAsBoolean(); + } + + public void setPasswordCharacterEncoding(String characterSet) { + this.passwordCharacterEncoding.setValue(characterSet); + } + + public String getPasswordCharacterEncoding() { + return this.passwordCharacterEncoding.getValueAsString(); + } + + public void setExceptionInterceptors(String exceptionInterceptors) { + this.exceptionInterceptors.setValue(exceptionInterceptors); + } + + public String getExceptionInterceptors() { + return this.exceptionInterceptors.getValueAsString(); + } + + public void setMaxAllowedPacket(int max) throws SQLException { + this.maxAllowedPacket.setValue(max, getExceptionInterceptor()); + } + + public int getMaxAllowedPacket() { + return this.maxAllowedPacket.getValueAsInt(); + } + + public boolean getQueryTimeoutKillsConnection() { + return this.queryTimeoutKillsConnection.getValueAsBoolean(); + } + + public void setQueryTimeoutKillsConnection(boolean queryTimeoutKillsConnection) { + this.queryTimeoutKillsConnection.setValue(queryTimeoutKillsConnection); + } + + public boolean getLoadBalanceValidateConnectionOnSwapServer() { + return this.loadBalanceValidateConnectionOnSwapServer.getValueAsBoolean(); + } + + public void setLoadBalanceValidateConnectionOnSwapServer( + boolean loadBalanceValidateConnectionOnSwapServer) { + this.loadBalanceValidateConnectionOnSwapServer.setValue(loadBalanceValidateConnectionOnSwapServer); + + } + + public String getLoadBalanceConnectionGroup() { + return loadBalanceConnectionGroup.getValueAsString(); + } + + public void setLoadBalanceConnectionGroup(String loadBalanceConnectionGroup) { + this.loadBalanceConnectionGroup.setValue(loadBalanceConnectionGroup); + } + + public String getLoadBalanceExceptionChecker() { + return loadBalanceExceptionChecker.getValueAsString(); + } + + public void setLoadBalanceExceptionChecker(String loadBalanceExceptionChecker) { + this.loadBalanceExceptionChecker.setValue(loadBalanceExceptionChecker); + } + + public String getLoadBalanceSQLStateFailover() { + return loadBalanceSQLStateFailover.getValueAsString(); + } + + public void setLoadBalanceSQLStateFailover(String loadBalanceSQLStateFailover) { + this.loadBalanceSQLStateFailover.setValue(loadBalanceSQLStateFailover); + } + + public String getLoadBalanceSQLExceptionSubclassFailover() { + return loadBalanceSQLExceptionSubclassFailover.getValueAsString(); + } + + public void setLoadBalanceSQLExceptionSubclassFailover(String loadBalanceSQLExceptionSubclassFailover) { + this.loadBalanceSQLExceptionSubclassFailover.setValue(loadBalanceSQLExceptionSubclassFailover); + } + + public boolean getLoadBalanceEnableJMX() { + return loadBalanceEnableJMX.getValueAsBoolean(); + } + + public void setLoadBalanceEnableJMX(boolean loadBalanceEnableJMX) { + this.loadBalanceEnableJMX.setValue(loadBalanceEnableJMX); + } + + public void setLoadBalanceAutoCommitStatementThreshold(int loadBalanceAutoCommitStatementThreshold) throws SQLException { + this.loadBalanceAutoCommitStatementThreshold.setValue(loadBalanceAutoCommitStatementThreshold, getExceptionInterceptor()); + } + + public int getLoadBalanceAutoCommitStatementThreshold() { + return loadBalanceAutoCommitStatementThreshold.getValueAsInt(); + } + + public void setLoadBalanceAutoCommitStatementRegex(String loadBalanceAutoCommitStatementRegex) { + this.loadBalanceAutoCommitStatementRegex.setValue(loadBalanceAutoCommitStatementRegex); + } + + public String getLoadBalanceAutoCommitStatementRegex() { + return loadBalanceAutoCommitStatementRegex.getValueAsString(); + } + + public void setIncludeThreadDumpInDeadlockExceptions(boolean flag) { + this.includeThreadDumpInDeadlockExceptions.setValue(flag); + } + + public boolean getIncludeThreadDumpInDeadlockExceptions() { + return includeThreadDumpInDeadlockExceptions.getValueAsBoolean(); + } + + public void setIncludeThreadNamesAsStatementComment(boolean flag) { + this.includeThreadNamesAsStatementComment.setValue(flag); + } + + public boolean getIncludeThreadNamesAsStatementComment() { + return includeThreadNamesAsStatementComment.getValueAsBoolean(); + } + + public void setAuthenticationPlugins(String authenticationPlugins) { + this.authenticationPlugins.setValue(authenticationPlugins); + } + + public String getAuthenticationPlugins() { + return this.authenticationPlugins.getValueAsString(); + } + + public void setDisabledAuthenticationPlugins(String disabledAuthenticationPlugins) { + this.disabledAuthenticationPlugins.setValue(disabledAuthenticationPlugins); + } + + public String getDisabledAuthenticationPlugins() { + return this.disabledAuthenticationPlugins.getValueAsString(); + } + + public void setDefaultAuthenticationPlugin(String defaultAuthenticationPlugin) { + this.defaultAuthenticationPlugin.setValue(defaultAuthenticationPlugin); + + } + + public String getDefaultAuthenticationPlugin() { + return this.defaultAuthenticationPlugin.getValueAsString(); + } + + public void setParseInfoCacheFactory(String factoryClassname) { + this.parseInfoCacheFactory.setValue(factoryClassname); + } + + public String getParseInfoCacheFactory() { + return this.parseInfoCacheFactory.getValueAsString(); + } + + public void setServerConfigCacheFactory(String factoryClassname) { + this.serverConfigCacheFactory.setValue(factoryClassname); + } + + public String getServerConfigCacheFactory() { + return this.serverConfigCacheFactory.getValueAsString(); + } + + public void setDisconnectOnExpiredPasswords(boolean disconnectOnExpiredPasswords) { + this.disconnectOnExpiredPasswords.setValue(disconnectOnExpiredPasswords); + } + + public boolean getDisconnectOnExpiredPasswords() { + return this.disconnectOnExpiredPasswords.getValueAsBoolean(); + } + + public boolean getAllowMasterDownConnections() { + return this.allowMasterDownConnections.getValueAsBoolean(); + } + + public void setAllowMasterDownConnections(boolean connectIfMasterDown) { + this.allowMasterDownConnections.setValue(connectIfMasterDown); + } + + public boolean getReplicationEnableJMX() { + return this.replicationEnableJMX.getValueAsBoolean(); + } + + public void setReplicationEnableJMX(boolean replicationEnableJMX) { + this.replicationEnableJMX.setValue(replicationEnableJMX); + + } + + public void setGetProceduresReturnsFunctions(boolean getProcedureReturnsFunctions) { + this.getProceduresReturnsFunctions.setValue(getProcedureReturnsFunctions); + } + + public boolean getGetProceduresReturnsFunctions() { + return this.getProceduresReturnsFunctions.getValueAsBoolean(); + } + + public void setDetectCustomCollations(boolean detectCustomCollations) { + this.detectCustomCollations.setValue(detectCustomCollations); + } + + public boolean getDetectCustomCollations() { + return this.detectCustomCollations.getValueAsBoolean(); + } + + public String getServerRSAPublicKeyFile() { + return this.serverRSAPublicKeyFile.getValueAsString(); + } + + public void setServerRSAPublicKeyFile(String serverRSAPublicKeyFile) throws SQLException { + if (this.serverRSAPublicKeyFile.getUpdateCount() > 0) { + throw SQLError.createSQLException( + Messages.getString("ConnectionProperties.dynamicChangeIsNotAllowed", new Object[]{"'serverRSAPublicKeyFile'"}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + this.serverRSAPublicKeyFile.setValue(serverRSAPublicKeyFile); + } + + public boolean getAllowPublicKeyRetrieval() { + return this.allowPublicKeyRetrieval.getValueAsBoolean(); + } + + public void setAllowPublicKeyRetrieval(boolean allowPublicKeyRetrieval) throws SQLException { + if (this.allowPublicKeyRetrieval.getUpdateCount() > 0) { + throw SQLError.createSQLException( + Messages.getString("ConnectionProperties.dynamicChangeIsNotAllowed", new Object[]{"'allowPublicKeyRetrieval'"}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + this.allowPublicKeyRetrieval.setValue(allowPublicKeyRetrieval); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionPropertiesTransform.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionPropertiesTransform.java (.../ConnectionPropertiesTransform.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ConnectionPropertiesTransform.java (.../ConnectionPropertiesTransform.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,25 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ + package com.mysql.jdbc; import java.sql.SQLException; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Constants.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Constants.java (.../Constants.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Constants.java (.../Constants.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -31,17 +30,23 @@ * * @version $Id$ */ -class Constants { +public class Constants { /** * Avoids allocation of empty byte[] when representing 0-length strings. */ public final static byte[] EMPTY_BYTE_ARRAY = new byte[0]; - + /** * I18N'd representation of the abbreviation for "ms" */ public final static String MILLIS_I18N = Messages.getString("Milliseconds"); + + public final static byte[] SLASH_STAR_SPACE_AS_BYTES = new byte[] { + (byte) '/', (byte) '*', (byte) ' ' }; + public final static byte[] SPACE_STAR_SLASH_SPACE_AS_BYTES = new byte[] { + (byte) ' ', (byte) '*', (byte) '/', (byte) ' ' }; + /** * Prevents instantiation */ Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/DatabaseMetaData.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/DatabaseMetaData.java (.../DatabaseMetaData.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/DatabaseMetaData.java (.../DatabaseMetaData.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,45 +1,50 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import java.io.UnsupportedEncodingException; +import static com.mysql.jdbc.DatabaseMetaData.ProcedureType.FUNCTION; +import static com.mysql.jdbc.DatabaseMetaData.ProcedureType.PROCEDURE; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Constructor; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; - import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; +import java.util.TreeSet; /** * JDBC Interface to Mysql functions @@ -63,46 +68,27 @@ * Exp $ */ public class DatabaseMetaData implements java.sql.DatabaseMetaData { - protected abstract class IterateBlock { - IteratorWithCleanup iterator; - IterateBlock(IteratorWithCleanup i) { - iterator = i; - } - - public void doForAll() throws SQLException { - try { - while (iterator.hasNext()) { - forEach(iterator.next()); - } - } finally { - iterator.close(); - } - } - - abstract void forEach(Object each) throws SQLException; - } - - protected abstract class IteratorWithCleanup { + protected abstract class IteratorWithCleanup { abstract void close() throws SQLException; abstract boolean hasNext() throws SQLException; - abstract Object next() throws SQLException; + abstract T next() throws SQLException; } - + class LocalAndReferencedColumns { String constraintName; - List localColumnsList; + List localColumnsList; String referencedCatalog; - List referencedColumnsList; + List referencedColumnsList; String referencedTable; - LocalAndReferencedColumns(List localColumns, List refColumns, + LocalAndReferencedColumns(List localColumns, List refColumns, String constName, String refCatalog, String refTable) { this.localColumnsList = localColumns; this.referencedColumnsList = refColumns; @@ -112,7 +98,7 @@ } } - protected class ResultSetIterator extends IteratorWithCleanup { + protected class ResultSetIterator extends IteratorWithCleanup { int colIndex; ResultSet resultSet; @@ -130,12 +116,12 @@ return resultSet.next(); } - Object next() throws SQLException { - return resultSet.getObject(colIndex); + String next() throws SQLException { + return resultSet.getObject(colIndex).toString(); } } - protected class SingleStringIterator extends IteratorWithCleanup { + protected class SingleStringIterator extends IteratorWithCleanup { boolean onFirst = true; String value; @@ -153,7 +139,7 @@ return onFirst; } - Object next() throws SQLException { + String next() throws SQLException { onFirst = false; return value; } @@ -184,6 +170,11 @@ TypeDescriptor(String typeInfo, String nullabilityInfo) throws SQLException { + if (typeInfo == null) { + throw SQLError.createSQLException("NULL typeinfo not supported.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + String mysqlType = ""; String fullMysqlType = null; @@ -206,9 +197,11 @@ boolean isUnsigned = false; - if (StringUtils.indexOfIgnoreCase(typeInfo, "unsigned") != -1) { - fullMysqlType = mysqlType + " unsigned"; - isUnsigned = true; + if ((StringUtils.indexOfIgnoreCase(typeInfo, "unsigned") != -1) && + (StringUtils.indexOfIgnoreCase(typeInfo, "set") != 0) && + (StringUtils.indexOfIgnoreCase(typeInfo, "enum") != 0)) { + fullMysqlType = mysqlType + " unsigned"; + isUnsigned = true; } else { fullMysqlType = mysqlType; } @@ -222,189 +215,192 @@ this.typeName = fullMysqlType; // Figure Out the Size - if (typeInfo != null) { - if (StringUtils.startsWithIgnoreCase(typeInfo, "enum")) { - String temp = typeInfo.substring(typeInfo.indexOf("("), - typeInfo.lastIndexOf(")")); - java.util.StringTokenizer tokenizer = new java.util.StringTokenizer( - temp, ","); - int maxLength = 0; + + if (StringUtils.startsWithIgnoreCase(typeInfo, "enum")) { + String temp = typeInfo.substring(typeInfo.indexOf("("), + typeInfo.lastIndexOf(")")); + java.util.StringTokenizer tokenizer = new java.util.StringTokenizer( + temp, ","); + int maxLength = 0; - while (tokenizer.hasMoreTokens()) { - maxLength = Math.max(maxLength, (tokenizer.nextToken() - .length() - 2)); - } + while (tokenizer.hasMoreTokens()) { + maxLength = Math.max(maxLength, (tokenizer.nextToken() + .length() - 2)); + } - this.columnSize = new Integer(maxLength); - this.decimalDigits = null; - } else if (StringUtils.startsWithIgnoreCase(typeInfo, "set")) { - String temp = typeInfo.substring(typeInfo.indexOf("("), - typeInfo.lastIndexOf(")")); - java.util.StringTokenizer tokenizer = new java.util.StringTokenizer( - temp, ","); - int maxLength = 0; + this.columnSize = Integer.valueOf(maxLength); + this.decimalDigits = null; + } else if (StringUtils.startsWithIgnoreCase(typeInfo, "set")) { + String temp = typeInfo.substring(typeInfo.indexOf("(") + 1, + typeInfo.lastIndexOf(")")); + java.util.StringTokenizer tokenizer = new java.util.StringTokenizer( + temp, ","); + int maxLength = 0; - while (tokenizer.hasMoreTokens()) { - String setMember = tokenizer.nextToken().trim(); + int numElements = tokenizer.countTokens(); + + if (numElements > 0) { + maxLength += (numElements - 1); + } + + while (tokenizer.hasMoreTokens()) { + String setMember = tokenizer.nextToken().trim(); - if (setMember.startsWith("'") - && setMember.endsWith("'")) { - maxLength += setMember.length() - 2; - } else { - maxLength += setMember.length(); - } + if (setMember.startsWith("'") + && setMember.endsWith("'")) { + maxLength += setMember.length() - 2; + } else { + maxLength += setMember.length(); } + } - this.columnSize = new Integer(maxLength); - this.decimalDigits = null; - } else if (typeInfo.indexOf(",") != -1) { - // Numeric with decimals - this.columnSize = new Integer(typeInfo.substring((typeInfo - .indexOf("(") + 1), (typeInfo.indexOf(","))).trim()); - this.decimalDigits = new Integer(typeInfo.substring( - (typeInfo.indexOf(",") + 1), - (typeInfo.indexOf(")"))).trim()); - } else { - this.columnSize = null; - this.decimalDigits = null; + this.columnSize = Integer.valueOf(maxLength); + this.decimalDigits = null; + } else if (typeInfo.indexOf(",") != -1) { + // Numeric with decimals + this.columnSize = Integer.valueOf(typeInfo.substring((typeInfo + .indexOf("(") + 1), (typeInfo.indexOf(","))).trim()); + this.decimalDigits = Integer.valueOf(typeInfo.substring( + (typeInfo.indexOf(",") + 1), + (typeInfo.indexOf(")"))).trim()); + } else { + this.columnSize = null; + this.decimalDigits = null; - /* If the size is specified with the DDL, use that */ - if ((StringUtils.indexOfIgnoreCase(typeInfo, "char") != -1 - || StringUtils.indexOfIgnoreCase(typeInfo, "text") != -1 - || StringUtils.indexOfIgnoreCase(typeInfo, "blob") != -1 - || StringUtils - .indexOfIgnoreCase(typeInfo, "binary") != -1 || StringUtils - .indexOfIgnoreCase(typeInfo, "bit") != -1) - && typeInfo.indexOf("(") != -1) { - int endParenIndex = typeInfo.indexOf(")"); + /* If the size is specified with the DDL, use that */ + if ((StringUtils.indexOfIgnoreCase(typeInfo, "char") != -1 + || StringUtils.indexOfIgnoreCase(typeInfo, "text") != -1 + || StringUtils.indexOfIgnoreCase(typeInfo, "blob") != -1 + || StringUtils + .indexOfIgnoreCase(typeInfo, "binary") != -1 || StringUtils + .indexOfIgnoreCase(typeInfo, "bit") != -1) + && typeInfo.indexOf("(") != -1) { + int endParenIndex = typeInfo.indexOf(")"); - if (endParenIndex == -1) { - endParenIndex = typeInfo.length(); - } + if (endParenIndex == -1) { + endParenIndex = typeInfo.length(); + } - this.columnSize = new Integer(typeInfo.substring( - (typeInfo.indexOf("(") + 1), endParenIndex).trim()); + this.columnSize = Integer.valueOf(typeInfo.substring( + (typeInfo.indexOf("(") + 1), endParenIndex).trim()); - // Adjust for pseudo-boolean - if (conn.getTinyInt1isBit() - && this.columnSize.intValue() == 1 - && StringUtils.startsWithIgnoreCase(typeInfo, - 0, "tinyint")) { - if (conn.getTransformedBitIsBoolean()) { - this.dataType = Types.BOOLEAN; - this.typeName = "BOOLEAN"; - } else { - this.dataType = Types.BIT; - this.typeName = "BIT"; - } + // Adjust for pseudo-boolean + if (conn.getTinyInt1isBit() + && this.columnSize.intValue() == 1 + && StringUtils.startsWithIgnoreCase(typeInfo, + 0, "tinyint")) { + if (conn.getTransformedBitIsBoolean()) { + this.dataType = Types.BOOLEAN; + this.typeName = "BOOLEAN"; + } else { + this.dataType = Types.BIT; + this.typeName = "BIT"; } - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "tinyint")) { - if (conn.getTinyInt1isBit() && typeInfo.indexOf("(1)") != -1) { - if (conn.getTransformedBitIsBoolean()) { - this.dataType = Types.BOOLEAN; - this.typeName = "BOOLEAN"; - } else { - this.dataType = Types.BIT; - this.typeName = "BIT"; - } + } + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "tinyint")) { + if (conn.getTinyInt1isBit() && typeInfo.indexOf("(1)") != -1) { + if (conn.getTransformedBitIsBoolean()) { + this.dataType = Types.BOOLEAN; + this.typeName = "BOOLEAN"; } else { - this.columnSize = new Integer(3); - this.decimalDigits = new Integer(0); + this.dataType = Types.BIT; + this.typeName = "BIT"; } - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "smallint")) { - this.columnSize = new Integer(5); - this.decimalDigits = new Integer(0); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "mediumint")) { - this.columnSize = new Integer(isUnsigned ? 8 : 7); - this.decimalDigits = new Integer(0); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "int")) { - this.columnSize = new Integer(10); - this.decimalDigits = new Integer(0); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "integer")) { - this.columnSize = new Integer(10); - this.decimalDigits = new Integer(0); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "bigint")) { - this.columnSize = new Integer(isUnsigned ? 20 : 19); - this.decimalDigits = new Integer(0); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "int24")) { - this.columnSize = new Integer(19); - this.decimalDigits = new Integer(0); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "real")) { - this.columnSize = new Integer(12); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "float")) { - this.columnSize = new Integer(12); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "decimal")) { - this.columnSize = new Integer(12); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "numeric")) { - this.columnSize = new Integer(12); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "double")) { - this.columnSize = new Integer(22); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "char")) { - this.columnSize = new Integer(1); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "varchar")) { - this.columnSize = new Integer(255); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "date")) { - this.columnSize = null; - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "time")) { - this.columnSize = null; - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "timestamp")) { - this.columnSize = null; - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "datetime")) { - this.columnSize = null; - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "tinyblob")) { - this.columnSize = new Integer(255); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "blob")) { - this.columnSize = new Integer(65535); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "mediumblob")) { - this.columnSize = new Integer(16777215); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "longblob")) { - this.columnSize = new Integer(Integer.MAX_VALUE); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "tinytext")) { - this.columnSize = new Integer(255); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "text")) { - this.columnSize = new Integer(65535); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "mediumtext")) { - this.columnSize = new Integer(16777215); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "longtext")) { - this.columnSize = new Integer(Integer.MAX_VALUE); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "enum")) { - this.columnSize = new Integer(255); - } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, - "set")) { - this.columnSize = new Integer(255); + } else { + this.columnSize = Integer.valueOf(3); + this.decimalDigits = Integer.valueOf(0); } - + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "smallint")) { + this.columnSize = Integer.valueOf(5); + this.decimalDigits = Integer.valueOf(0); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "mediumint")) { + this.columnSize = Integer.valueOf(isUnsigned ? 8 : 7); + this.decimalDigits = Integer.valueOf(0); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "int")) { + this.columnSize = Integer.valueOf(10); + this.decimalDigits = Integer.valueOf(0); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "integer")) { + this.columnSize = Integer.valueOf(10); + this.decimalDigits = Integer.valueOf(0); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "bigint")) { + this.columnSize = Integer.valueOf(isUnsigned ? 20 : 19); + this.decimalDigits = Integer.valueOf(0); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "int24")) { + this.columnSize = Integer.valueOf(19); + this.decimalDigits = Integer.valueOf(0); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "real")) { + this.columnSize = Integer.valueOf(12); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "float")) { + this.columnSize = Integer.valueOf(12); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "decimal")) { + this.columnSize = Integer.valueOf(12); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "numeric")) { + this.columnSize = Integer.valueOf(12); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "double")) { + this.columnSize = Integer.valueOf(22); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "char")) { + this.columnSize = Integer.valueOf(1); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "varchar")) { + this.columnSize = Integer.valueOf(255); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "timestamp")) { + this.columnSize = Integer.valueOf(19); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "datetime")) { + this.columnSize = Integer.valueOf(19); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "date")) { + this.columnSize = Integer.valueOf(10); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "time")) { + this.columnSize = Integer.valueOf(8); + + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "tinyblob")) { + this.columnSize = Integer.valueOf(255); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "blob")) { + this.columnSize = Integer.valueOf(65535); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "mediumblob")) { + this.columnSize = Integer.valueOf(16777215); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "longblob")) { + this.columnSize = Integer.valueOf(Integer.MAX_VALUE); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "tinytext")) { + this.columnSize = Integer.valueOf(255); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "text")) { + this.columnSize = Integer.valueOf(65535); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "mediumtext")) { + this.columnSize = Integer.valueOf(16777215); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "longtext")) { + this.columnSize = Integer.valueOf(Integer.MAX_VALUE); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "enum")) { + this.columnSize = Integer.valueOf(255); + } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, + "set")) { + this.columnSize = Integer.valueOf(255); } - } else { - this.decimalDigits = null; - this.columnSize = null; + } // BUFFER_LENGTH @@ -419,6 +415,10 @@ this.nullability = java.sql.DatabaseMetaData.columnNullable; this.isNullable = "YES"; + } else if (nullabilityInfo.equals("UNKNOWN")) { + this.nullability = java.sql.DatabaseMetaData.columnNullableUnknown; + this.isNullable = ""; + // IS_NULLABLE } else { this.nullability = java.sql.DatabaseMetaData.columnNoNulls; @@ -430,9 +430,228 @@ } } } + + /** + * Helper class to provide means of comparing indexes by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION. + */ + protected class IndexMetaDataKey implements Comparable { + Boolean columnNonUnique; + Short columnType; + String columnIndexName; + Short columnOrdinalPosition; - private static String mysqlKeywordsThatArentSQL92; + IndexMetaDataKey(boolean columnNonUnique, short columnType, String columnIndexName, + short columnOrdinalPosition) { + this.columnNonUnique = columnNonUnique; + this.columnType = columnType; + this.columnIndexName = columnIndexName; + this.columnOrdinalPosition = columnOrdinalPosition; + } + public int compareTo(IndexMetaDataKey indexInfoKey) { + int compareResult; + + if ((compareResult = columnNonUnique.compareTo(indexInfoKey.columnNonUnique)) != 0) { + return compareResult; + } + if ((compareResult = columnType.compareTo(indexInfoKey.columnType)) != 0) { + return compareResult; + } + if ((compareResult = columnIndexName.compareTo(indexInfoKey.columnIndexName)) != 0) { + return compareResult; + } + return columnOrdinalPosition.compareTo(indexInfoKey.columnOrdinalPosition); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (obj == this) { + return true; + } + + if (!(obj instanceof IndexMetaDataKey)) { + return false; + } + return compareTo((IndexMetaDataKey) obj) == 0; + } + } + + /** + * Helper class to provide means of comparing tables by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM and TABLE_NAME. + */ + protected class TableMetaDataKey implements Comparable { + String tableType; + String tableCat; + String tableSchem; + String tableName; + + TableMetaDataKey(String tableType, String tableCat, String tableSchem, String tableName) { + this.tableType = tableType == null ? "" : tableType; + this.tableCat = tableCat == null ? "" : tableCat; + this.tableSchem = tableSchem == null ? "" : tableSchem; + this.tableName = tableName == null ? "" : tableName; + } + + public int compareTo(TableMetaDataKey tablesKey) { + int compareResult; + + if ((compareResult = tableType.compareTo(tablesKey.tableType)) != 0) { + return compareResult; + } + if ((compareResult = tableCat.compareTo(tablesKey.tableCat)) != 0) { + return compareResult; + } + if ((compareResult = tableSchem.compareTo(tablesKey.tableSchem)) != 0) { + return compareResult; + } + return tableName.compareTo(tablesKey.tableName); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (obj == this) { + return true; + } + + if (!(obj instanceof TableMetaDataKey)) { + return false; + } + return compareTo((TableMetaDataKey) obj) == 0; + } + } + + /** + * Helper/wrapper class to provide means of sorting objects by using a sorting key. + */ + protected class ComparableWrapper, V> implements + Comparable> { + K key; + V value; + + public ComparableWrapper(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public int compareTo(ComparableWrapper other) { + return getKey().compareTo(other.getKey()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (obj == this) { + return true; + } + + if (!(obj instanceof ComparableWrapper)) { + return false; + } + + Object otherKey = ((ComparableWrapper) obj).getKey(); + return key.equals(otherKey); + } + + @Override + public String toString() { + return "{KEY:" + key + "; VALUE:" + value +"}"; + } + } + + /** + * Enumeration for Table Types + */ + protected enum TableType { + LOCAL_TEMPORARY("LOCAL TEMPORARY"), SYSTEM_TABLE("SYSTEM TABLE"), SYSTEM_VIEW("SYSTEM VIEW"), TABLE("TABLE", + new String[] { "BASE TABLE" }), VIEW("VIEW"), UNKNOWN("UNKNOWN"); + + private String name; + private byte[] nameAsBytes; + private String[] synonyms; + + TableType(String tableTypeName) { + this(tableTypeName, null); + } + + TableType(String tableTypeName, String[] tableTypeSynonyms) { + name = tableTypeName; + nameAsBytes = tableTypeName.getBytes(); + synonyms = tableTypeSynonyms; + } + + String getName() { + return name; + } + + byte[] asBytes() { + return nameAsBytes; + } + + boolean equalsTo(String tableTypeName) { + return name.equalsIgnoreCase(tableTypeName); + } + + static TableType getTableTypeEqualTo(String tableTypeName) { + for (TableType tableType : TableType.values()) { + if (tableType.equalsTo(tableTypeName)) { + return tableType; + } + } + return UNKNOWN; + } + + boolean compliesWith(String tableTypeName) { + if (equalsTo(tableTypeName)) { + return true; + } + if (synonyms != null) { + for (String synonym : synonyms) { + if (synonym.equalsIgnoreCase(tableTypeName)) { + return true; + } + } + } + return false; + } + + static TableType getTableTypeCompliantWith(String tableTypeName) { + for (TableType tableType : TableType.values()) { + if (tableType.compliesWith(tableTypeName)) { + return tableType; + } + } + return UNKNOWN; + } + } + + /** + * Enumeration for Procedure Types + */ + protected enum ProcedureType { + PROCEDURE, FUNCTION; + } + + protected static final int MAX_IDENTIFIER_LENGTH = 64; + private static final int DEFERRABILITY = 13; private static final int DELETE_RULE = 10; @@ -466,155 +685,171 @@ /** The table type for generic tables that support foreign keys. */ private static final String SUPPORTS_FK = "SUPPORTS_FK"; - private static final byte[] TABLE_AS_BYTES = "TABLE".getBytes(); + protected static final byte[] TABLE_AS_BYTES = "TABLE".getBytes(); + protected static final byte[] SYSTEM_TABLE_AS_BYTES = "SYSTEM TABLE".getBytes(); + private static final int UPDATE_RULE = 9; - private static final byte[] VIEW_AS_BYTES = "VIEW".getBytes(); - + protected static final byte[] VIEW_AS_BYTES = "VIEW".getBytes(); + + private static final Constructor JDBC_4_DBMD_SHOW_CTOR; + + private static final Constructor JDBC_4_DBMD_IS_CTOR; + static { - // Current as-of MySQL-5.1.16 - String[] allMySQLKeywords = new String[] { "ACCESSIBLE", "ADD", "ALL", - "ALTER", "ANALYZE", "AND", "AS", "ASC", "ASENSITIVE", "BEFORE", - "BETWEEN", "BIGINT", "BINARY", "BLOB", "BOTH", "BY", "CALL", - "CASCADE", "CASE", "CHANGE", "CHAR", "CHARACTER", "CHECK", - "COLLATE", "COLUMN", "CONDITION", "CONNECTION", "CONSTRAINT", - "CONTINUE", "CONVERT", "CREATE", "CROSS", "CURRENT_DATE", - "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", - "DATABASE", "DATABASES", "DAY_HOUR", "DAY_MICROSECOND", - "DAY_MINUTE", "DAY_SECOND", "DEC", "DECIMAL", "DECLARE", - "DEFAULT", "DELAYED", "DELETE", "DESC", "DESCRIBE", - "DETERMINISTIC", "DISTINCT", "DISTINCTROW", "DIV", "DOUBLE", - "DROP", "DUAL", "EACH", "ELSE", "ELSEIF", "ENCLOSED", - "ESCAPED", "EXISTS", "EXIT", "EXPLAIN", "FALSE", "FETCH", - "FLOAT", "FLOAT4", "FLOAT8", "FOR", "FORCE", "FOREIGN", "FROM", - "FULLTEXT", "GRANT", "GROUP", "HAVING", "HIGH_PRIORITY", - "HOUR_MICROSECOND", "HOUR_MINUTE", "HOUR_SECOND", "IF", - "IGNORE", "IN", "INDEX", "INFILE", "INNER", "INOUT", - "INSENSITIVE", "INSERT", "INT", "INT1", "INT2", "INT3", "INT4", - "INT8", "INTEGER", "INTERVAL", "INTO", "IS", "ITERATE", "JOIN", - "KEY", "KEYS", "KILL", "LEADING", "LEAVE", "LEFT", "LIKE", - "LIMIT", "LINEAR", "LINES", "LOAD", "LOCALTIME", - "LOCALTIMESTAMP", "LOCK", "LONG", "LONGBLOB", "LONGTEXT", - "LOOP", "LOW_PRIORITY", "MATCH", "MEDIUMBLOB", "MEDIUMINT", - "MEDIUMTEXT", "MIDDLEINT", "MINUTE_MICROSECOND", - "MINUTE_SECOND", "MOD", "MODIFIES", "NATURAL", "NOT", - "NO_WRITE_TO_BINLOG", "NULL", "NUMERIC", "ON", "OPTIMIZE", - "OPTION", "OPTIONALLY", "OR", "ORDER", "OUT", "OUTER", - "OUTFILE", "PRECISION", "PRIMARY", "PROCEDURE", "PURGE", - "RANGE", "READ", "READS", "READ_ONLY", "READ_WRITE", "REAL", - "REFERENCES", "REGEXP", "RELEASE", "RENAME", "REPEAT", - "REPLACE", "REQUIRE", "RESTRICT", "RETURN", "REVOKE", "RIGHT", - "RLIKE", "SCHEMA", "SCHEMAS", "SECOND_MICROSECOND", "SELECT", - "SENSITIVE", "SEPARATOR", "SET", "SHOW", "SMALLINT", "SPATIAL", - "SPECIFIC", "SQL", "SQLEXCEPTION", "SQLSTATE", "SQLWARNING", - "SQL_BIG_RESULT", "SQL_CALC_FOUND_ROWS", "SQL_SMALL_RESULT", - "SSL", "STARTING", "STRAIGHT_JOIN", "TABLE", "TERMINATED", - "THEN", "TINYBLOB", "TINYINT", "TINYTEXT", "TO", "TRAILING", - "TRIGGER", "TRUE", "UNDO", "UNION", "UNIQUE", "UNLOCK", - "UNSIGNED", "UPDATE", "USAGE", "USE", "USING", "UTC_DATE", - "UTC_TIME", "UTC_TIMESTAMP", "VALUES", "VARBINARY", "VARCHAR", - "VARCHARACTER", "VARYING", "WHEN", "WHERE", "WHILE", "WITH", - "WRITE", "X509", "XOR", "YEAR_MONTH", "ZEROFILL" }; - - String[] sql92Keywords = new String[] { "ABSOLUTE", "EXEC", "OVERLAPS", - "ACTION", "EXECUTE", "PAD", "ADA", "EXISTS", "PARTIAL", "ADD", - "EXTERNAL", "PASCAL", "ALL", "EXTRACT", "POSITION", "ALLOCATE", - "FALSE", "PRECISION", "ALTER", "FETCH", "PREPARE", "AND", - "FIRST", "PRESERVE", "ANY", "FLOAT", "PRIMARY", "ARE", "FOR", - "PRIOR", "AS", "FOREIGN", "PRIVILEGES", "ASC", "FORTRAN", - "PROCEDURE", "ASSERTION", "FOUND", "PUBLIC", "AT", "FROM", - "READ", "AUTHORIZATION", "FULL", "REAL", "AVG", "GET", - "REFERENCES", "BEGIN", "GLOBAL", "RELATIVE", "BETWEEN", "GO", - "RESTRICT", "BIT", "GOTO", "REVOKE", "BIT_LENGTH", "GRANT", - "RIGHT", "BOTH", "GROUP", "ROLLBACK", "BY", "HAVING", "ROWS", - "CASCADE", "HOUR", "SCHEMA", "CASCADED", "IDENTITY", "SCROLL", - "CASE", "IMMEDIATE", "SECOND", "CAST", "IN", "SECTION", - "CATALOG", "INCLUDE", "SELECT", "CHAR", "INDEX", "SESSION", - "CHAR_LENGTH", "INDICATOR", "SESSION_USER", "CHARACTER", - "INITIALLY", "SET", "CHARACTER_LENGTH", "INNER", "SIZE", - "CHECK", "INPUT", "SMALLINT", "CLOSE", "INSENSITIVE", "SOME", - "COALESCE", "INSERT", "SPACE", "COLLATE", "INT", "SQL", - "COLLATION", "INTEGER", "SQLCA", "COLUMN", "INTERSECT", - "SQLCODE", "COMMIT", "INTERVAL", "SQLERROR", "CONNECT", "INTO", - "SQLSTATE", "CONNECTION", "IS", "SQLWARNING", "CONSTRAINT", - "ISOLATION", "SUBSTRING", "CONSTRAINTS", "JOIN", "SUM", - "CONTINUE", "KEY", "SYSTEM_USER", "CONVERT", "LANGUAGE", - "TABLE", "CORRESPONDING", "LAST", "TEMPORARY", "COUNT", - "LEADING", "THEN", "CREATE", "LEFT", "TIME", "CROSS", "LEVEL", - "TIMESTAMP", "CURRENT", "LIKE", "TIMEZONE_HOUR", - "CURRENT_DATE", "LOCAL", "TIMEZONE_MINUTE", "CURRENT_TIME", - "LOWER", "TO", "CURRENT_TIMESTAMP", "MATCH", "TRAILING", - "CURRENT_USER", "MAX", "TRANSACTION", "CURSOR", "MIN", - "TRANSLATE", "DATE", "MINUTE", "TRANSLATION", "DAY", "MODULE", - "TRIM", "DEALLOCATE", "MONTH", "TRUE", "DEC", "NAMES", "UNION", - "DECIMAL", "NATIONAL", "UNIQUE", "DECLARE", "NATURAL", - "UNKNOWN", "DEFAULT", "NCHAR", "UPDATE", "DEFERRABLE", "NEXT", - "UPPER", "DEFERRED", "NO", "USAGE", "DELETE", "NONE", "USER", - "DESC", "NOT", "USING", "DESCRIBE", "NULL", "VALUE", - "DESCRIPTOR", "NULLIF", "VALUES", "DIAGNOSTICS", "NUMERIC", - "VARCHAR", "DISCONNECT", "OCTET_LENGTH", "VARYING", "DISTINCT", - "OF", "VIEW", "DOMAIN", "ON", "WHEN", "DOUBLE", "ONLY", - "WHENEVER", "DROP", "OPEN", "WHERE", "ELSE", "OPTION", "WITH", - "END", "OR", "WORK", "END-EXEC", "ORDER", "WRITE", "ESCAPE", - "OUTER", "YEAR", "EXCEPT", "OUTPUT", "ZONE", "EXCEPTION" }; - - TreeMap mySQLKeywordMap = new TreeMap(); - - for (int i = 0; i < allMySQLKeywords.length; i++) { - mySQLKeywordMap.put(allMySQLKeywords[i], null); + if (Util.isJdbc4()) { + try { + JDBC_4_DBMD_SHOW_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4DatabaseMetaData").getConstructor( + new Class[] { com.mysql.jdbc.MySQLConnection.class, + String.class }); + JDBC_4_DBMD_IS_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4DatabaseMetaDataUsingInfoSchema") + .getConstructor( + new Class[] { com.mysql.jdbc.MySQLConnection.class, + String.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_DBMD_IS_CTOR = null; + JDBC_4_DBMD_SHOW_CTOR = null; } - - HashMap sql92KeywordMap = new HashMap(sql92Keywords.length); - - for (int i = 0; i < sql92Keywords.length; i++) { - sql92KeywordMap.put(sql92Keywords[i], null); - } - - Iterator it = sql92KeywordMap.keySet().iterator(); - - while (it.hasNext()) { - mySQLKeywordMap.remove(it.next()); - } - - StringBuffer keywordBuf = new StringBuffer(); - - it = mySQLKeywordMap.keySet().iterator(); - - if (it.hasNext()) { - keywordBuf.append(it.next().toString()); - } - - while (it.hasNext()) { - keywordBuf.append(","); - keywordBuf.append(it.next().toString()); - } - - mysqlKeywordsThatArentSQL92 = keywordBuf.toString(); } - static java.sql.ResultSet buildResultSet(com.mysql.jdbc.Field[] fields, - java.util.ArrayList rows, Connection c) throws SQLException { - int fieldsLength = fields.length; + // MySQL reserved words (all versions superset) + private static final String[] MYSQL_KEYWORDS = new String[] { "ACCESSIBLE", "ADD", "ALL", "ALTER", "ANALYZE", + "AND", "AS", "ASC", "ASENSITIVE", "BEFORE", "BETWEEN", "BIGINT", "BINARY", "BLOB", "BOTH", "BY", "CALL", + "CASCADE", "CASE", "CHANGE", "CHAR", "CHARACTER", "CHECK", "COLLATE", "COLUMN", "CONDITION", "CONSTRAINT", + "CONTINUE", "CONVERT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", + "CURRENT_USER", "CURSOR", "DATABASE", "DATABASES", "DAY_HOUR", "DAY_MICROSECOND", "DAY_MINUTE", + "DAY_SECOND", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DELAYED", "DELETE", "DESC", "DESCRIBE", + "DETERMINISTIC", "DISTINCT", "DISTINCTROW", "DIV", "DOUBLE", "DROP", "DUAL", "EACH", "ELSE", "ELSEIF", + "ENCLOSED", "ESCAPED", "EXISTS", "EXIT", "EXPLAIN", "FALSE", "FETCH", "FLOAT", "FLOAT4", "FLOAT8", "FOR", + "FORCE", "FOREIGN", "FROM", "FULLTEXT", "GET", "GRANT", "GROUP", "HAVING", "HIGH_PRIORITY", + "HOUR_MICROSECOND", "HOUR_MINUTE", "HOUR_SECOND", "IF", "IGNORE", "IN", "INDEX", "INFILE", "INNER", + "INOUT", "INSENSITIVE", "INSERT", "INT", "INT1", "INT2", "INT3", "INT4", "INT8", "INTEGER", "INTERVAL", + "INTO", "IO_AFTER_GTIDS", "IO_BEFORE_GTIDS", "IS", "ITERATE", "JOIN", "KEY", "KEYS", "KILL", "LEADING", + "LEAVE", "LEFT", "LIKE", "LIMIT", "LINEAR", "LINES", "LOAD", "LOCALTIME", "LOCALTIMESTAMP", "LOCK", "LONG", + "LONGBLOB", "LONGTEXT", "LOOP", "LOW_PRIORITY", "MASTER_BIND", "MASTER_SSL_VERIFY_SERVER_CERT", "MATCH", + "MAXVALUE", "MEDIUMBLOB", "MEDIUMINT", "MEDIUMTEXT", "MIDDLEINT", "MINUTE_MICROSECOND", "MINUTE_SECOND", + "MOD", "MODIFIES", "NATURAL", "NONBLOCKING", "NOT", "NO_WRITE_TO_BINLOG", "NULL", "NUMERIC", "ON", + "OPTIMIZE", "OPTION", "OPTIONALLY", "OR", "ORDER", "OUT", "OUTER", "OUTFILE", "PARTITION", "PRECISION", + "PRIMARY", "PROCEDURE", "PURGE", "RANGE", "READ", "READS", "READ_WRITE", "REAL", "REFERENCES", "REGEXP", + "RELEASE", "RENAME", "REPEAT", "REPLACE", "REQUIRE", "RESIGNAL", "RESTRICT", "RETURN", "REVOKE", "RIGHT", + "RLIKE", "SCHEMA", "SCHEMAS", "SECOND_MICROSECOND", "SELECT", "SENSITIVE", "SEPARATOR", "SET", "SHOW", + "SIGNAL", "SMALLINT", "SPATIAL", "SPECIFIC", "SQL", "SQLEXCEPTION", "SQLSTATE", "SQLWARNING", + "SQL_BIG_RESULT", "SQL_CALC_FOUND_ROWS", "SQL_SMALL_RESULT", "SSL", "STARTING", "STRAIGHT_JOIN", "TABLE", + "TERMINATED", "THEN", "TINYBLOB", "TINYINT", "TINYTEXT", "TO", "TRAILING", "TRIGGER", "TRUE", "UNDO", + "UNION", "UNIQUE", "UNLOCK", "UNSIGNED", "UPDATE", "USAGE", "USE", "USING", "UTC_DATE", "UTC_TIME", + "UTC_TIMESTAMP", "VALUES", "VARBINARY", "VARCHAR", "VARCHARACTER", "VARYING", "WHEN", "WHERE", "WHILE", + "WITH", "WRITE", "XOR", "YEAR_MONTH", "ZEROFILL" }; - for (int i = 0; i < fieldsLength; i++) { - fields[i].setConnection(c); - fields[i].setUseOldNameMetadata(true); - } + // SQL:92 reserved words from 'ANSI X3.135-1992, January 4, 1993' + private static final String[] SQL92_KEYWORDS = new String[] { "ABSOLUTE", "ACTION", "ADD", "ALL", "ALLOCATE", + "ALTER", "AND", "ANY", "ARE", "AS", "ASC", "ASSERTION", "AT", "AUTHORIZATION", "AVG", "BEGIN", "BETWEEN", + "BIT", "BIT_LENGTH", "BOTH", "BY", "CASCADE", "CASCADED", "CASE", "CAST", "CATALOG", "CHAR", "CHARACTER", + "CHARACTER_LENGTH", "CHAR_LENGTH", "CHECK", "CLOSE", "COALESCE", "COLLATE", "COLLATION", "COLUMN", + "COMMIT", "CONNECT", "CONNECTION", "CONSTRAINT", "CONSTRAINTS", "CONTINUE", "CONVERT", "CORRESPONDING", + "COUNT", "CREATE", "CROSS", "CURRENT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", + "CURSOR", "DATE", "DAY", "DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DEFERRABLE", "DEFERRED", + "DELETE", "DESC", "DESCRIBE", "DESCRIPTOR", "DIAGNOSTICS", "DISCONNECT", "DISTINCT", "DOMAIN", "DOUBLE", + "DROP", "ELSE", "END", "END-EXEC", "ESCAPE", "EXCEPT", "EXCEPTION", "EXEC", "EXECUTE", "EXISTS", + "EXTERNAL", "EXTRACT", "FALSE", "FETCH", "FIRST", "FLOAT", "FOR", "FOREIGN", "FOUND", "FROM", "FULL", + "GET", "GLOBAL", "GO", "GOTO", "GRANT", "GROUP", "HAVING", "HOUR", "IDENTITY", "IMMEDIATE", "IN", + "INDICATOR", "INITIALLY", "INNER", "INPUT", "INSENSITIVE", "INSERT", "INT", "INTEGER", "INTERSECT", + "INTERVAL", "INTO", "IS", "ISOLATION", "JOIN", "KEY", "LANGUAGE", "LAST", "LEADING", "LEFT", "LEVEL", + "LIKE", "LOCAL", "LOWER", "MATCH", "MAX", "MIN", "MINUTE", "MODULE", "MONTH", "NAMES", "NATIONAL", + "NATURAL", "NCHAR", "NEXT", "NO", "NOT", "NULL", "NULLIF", "NUMERIC", "OCTET_LENGTH", "OF", "ON", "ONLY", + "OPEN", "OPTION", "OR", "ORDER", "OUTER", "OUTPUT", "OVERLAPS", "PAD", "PARTIAL", "POSITION", "PRECISION", + "PREPARE", "PRESERVE", "PRIMARY", "PRIOR", "PRIVILEGES", "PROCEDURE", "PUBLIC", "READ", "REAL", + "REFERENCES", "RELATIVE", "RESTRICT", "REVOKE", "RIGHT", "ROLLBACK", "ROWS", "SCHEMA", "SCROLL", "SECOND", + "SECTION", "SELECT", "SESSION", "SESSION_USER", "SET", "SIZE", "SMALLINT", "SOME", "SPACE", "SQL", + "SQLCODE", "SQLERROR", "SQLSTATE", "SUBSTRING", "SUM", "SYSTEM_USER", "TABLE", "TEMPORARY", "THEN", "TIME", + "TIMESTAMP", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRAILING", "TRANSACTION", "TRANSLATE", + "TRANSLATION", "TRIM", "TRUE", "UNION", "UNIQUE", "UNKNOWN", "UPDATE", "UPPER", "USAGE", "USER", "USING", + "VALUE", "VALUES", "VARCHAR", "VARYING", "VIEW", "WHEN", "WHENEVER", "WHERE", "WITH", "WORK", "WRITE", + "YEAR", "ZONE" }; - return new com.mysql.jdbc.ResultSet(c.getCatalog(), fields, - new RowDataStatic(rows), c, null); - } + // SQL:2003 reserved words from 'ISO/IEC 9075-2:2003 (E), 2003-07-25' + private static final String[] SQL2003_KEYWORDS = new String[] { "ABS", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", + "ARE", "ARRAY", "AS", "ASENSITIVE", "ASYMMETRIC", "AT", "ATOMIC", "AUTHORIZATION", "AVG", "BEGIN", + "BETWEEN", "BIGINT", "BINARY", "BLOB", "BOOLEAN", "BOTH", "BY", "CALL", "CALLED", "CARDINALITY", + "CASCADED", "CASE", "CAST", "CEIL", "CEILING", "CHAR", "CHARACTER", "CHARACTER_LENGTH", "CHAR_LENGTH", + "CHECK", "CLOB", "CLOSE", "COALESCE", "COLLATE", "COLLECT", "COLUMN", "COMMIT", "CONDITION", "CONNECT", + "CONSTRAINT", "CONVERT", "CORR", "CORRESPONDING", "COUNT", "COVAR_POP", "COVAR_SAMP", "CREATE", "CROSS", + "CUBE", "CUME_DIST", "CURRENT", "CURRENT_DATE", "CURRENT_DEFAULT_TRANSFORM_GROUP", "CURRENT_PATH", + "CURRENT_ROLE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_TRANSFORM_GROUP_FOR_TYPE", "CURRENT_USER", + "CURSOR", "CYCLE", "DATE", "DAY", "DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DELETE", + "DENSE_RANK", "DEREF", "DESCRIBE", "DETERMINISTIC", "DISCONNECT", "DISTINCT", "DOUBLE", "DROP", "DYNAMIC", + "EACH", "ELEMENT", "ELSE", "END", "END-EXEC", "ESCAPE", "EVERY", "EXCEPT", "EXEC", "EXECUTE", "EXISTS", + "EXP", "EXTERNAL", "EXTRACT", "FALSE", "FETCH", "FILTER", "FLOAT", "FLOOR", "FOR", "FOREIGN", "FREE", + "FROM", "FULL", "FUNCTION", "FUSION", "GET", "GLOBAL", "GRANT", "GROUP", "GROUPING", "HAVING", "HOLD", + "HOUR", "IDENTITY", "IN", "INDICATOR", "INNER", "INOUT", "INSENSITIVE", "INSERT", "INT", "INTEGER", + "INTERSECT", "INTERSECTION", "INTERVAL", "INTO", "IS", "JOIN", "LANGUAGE", "LARGE", "LATERAL", "LEADING", + "LEFT", "LIKE", "LN", "LOCAL", "LOCALTIME", "LOCALTIMESTAMP", "LOWER", "MATCH", "MAX", "MEMBER", "MERGE", + "METHOD", "MIN", "MINUTE", "MOD", "MODIFIES", "MODULE", "MONTH", "MULTISET", "NATIONAL", "NATURAL", + "NCHAR", "NCLOB", "NEW", "NO", "NONE", "NORMALIZE", "NOT", "NULL", "NULLIF", "NUMERIC", "OCTET_LENGTH", + "OF", "OLD", "ON", "ONLY", "OPEN", "OR", "ORDER", "OUT", "OUTER", "OVER", "OVERLAPS", "OVERLAY", + "PARAMETER", "PARTITION", "PERCENTILE_CONT", "PERCENTILE_DISC", "PERCENT_RANK", "POSITION", "POWER", + "PRECISION", "PREPARE", "PRIMARY", "PROCEDURE", "RANGE", "RANK", "READS", "REAL", "RECURSIVE", "REF", + "REFERENCES", "REFERENCING", "REGR_AVGX", "REGR_AVGY", "REGR_COUNT", "REGR_INTERCEPT", "REGR_R2", + "REGR_SLOPE", "REGR_SXX", "REGR_SXY", "REGR_SYY", "RELEASE", "RESULT", "RETURN", "RETURNS", "REVOKE", + "RIGHT", "ROLLBACK", "ROLLUP", "ROW", "ROWS", "ROW_NUMBER", "SAVEPOINT", "SCOPE", "SCROLL", "SEARCH", + "SECOND", "SELECT", "SENSITIVE", "SESSION_USER", "SET", "SIMILAR", "SMALLINT", "SOME", "SPECIFIC", + "SPECIFICTYPE", "SQL", "SQLEXCEPTION", "SQLSTATE", "SQLWARNING", "SQRT", "START", "STATIC", "STDDEV_POP", + "STDDEV_SAMP", "SUBMULTISET", "SUBSTRING", "SUM", "SYMMETRIC", "SYSTEM", "SYSTEM_USER", "TABLE", + "TABLESAMPLE", "THEN", "TIME", "TIMESTAMP", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRAILING", + "TRANSLATE", "TRANSLATION", "TREAT", "TRIGGER", "TRIM", "TRUE", "UESCAPE", "UNION", "UNIQUE", "UNKNOWN", + "UNNEST", "UPDATE", "UPPER", "USER", "USING", "VALUE", "VALUES", "VARCHAR", "VARYING", "VAR_POP", + "VAR_SAMP", "WHEN", "WHENEVER", "WHERE", "WIDTH_BUCKET", "WINDOW", "WITH", "WITHIN", "WITHOUT", "YEAR" }; + private static volatile String mysqlKeywords = null; + /** The connection to the database */ - protected Connection conn; + protected MySQLConnection conn; /** The 'current' database name being used */ protected String database = null; /** What character to use when quoting identifiers */ protected String quotedId = null; + // We need to provide factory-style methods so we can support both JDBC3 (and older) + // and JDBC4 runtimes, otherwise the class verifier complains... + + protected static DatabaseMetaData getInstance( + MySQLConnection connToSet, String databaseToSet, boolean checkForInfoSchema) + throws SQLException { + if (!Util.isJdbc4()) { + if (checkForInfoSchema && connToSet != null + && connToSet.getUseInformationSchema() + && connToSet.versionMeetsMinimum(5, 0, 7)) { + return new DatabaseMetaDataUsingInfoSchema(connToSet, + databaseToSet); + } + + return new DatabaseMetaData(connToSet, databaseToSet); + } + + if (checkForInfoSchema && connToSet != null + && connToSet.getUseInformationSchema() + && connToSet.versionMeetsMinimum(5, 0, 7)) { + + return (DatabaseMetaData) Util.handleNewInstance( + JDBC_4_DBMD_IS_CTOR, new Object[] { connToSet, + databaseToSet }, connToSet.getExceptionInterceptor()); + } + + return (DatabaseMetaData) Util.handleNewInstance(JDBC_4_DBMD_SHOW_CTOR, + new Object[] { connToSet, databaseToSet }, connToSet.getExceptionInterceptor()); + } + /** * Creates a new DatabaseMetaData object. * @@ -623,10 +858,11 @@ * @param databaseToSet * DOCUMENT ME! */ - public DatabaseMetaData(Connection connToSet, String databaseToSet) { + protected DatabaseMetaData(MySQLConnection connToSet, String databaseToSet) { this.conn = connToSet; this.database = databaseToSet; - + this.exceptionInterceptor = this.conn.getExceptionInterceptor(); + try { this.quotedId = this.conn.supportsQuotedIdentifiers() ? getIdentifierQuoteString() : ""; @@ -662,13 +898,39 @@ } private java.sql.ResultSet buildResultSet(com.mysql.jdbc.Field[] fields, - java.util.ArrayList rows) throws SQLException { + java.util.ArrayList rows) throws SQLException { return buildResultSet(fields, rows, this.conn); } + + static java.sql.ResultSet buildResultSet(com.mysql.jdbc.Field[] fields, + java.util.ArrayList rows, MySQLConnection c) throws SQLException { + int fieldsLength = fields.length; - private void convertToJdbcFunctionList(String catalog, + for (int i = 0; i < fieldsLength; i++) { + int jdbcType = fields[i].getSQLType(); + + switch (jdbcType) { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + fields[i].setCharacterSet(c.getCharacterSetMetadata()); + break; + default: + // do nothing + } + + fields[i].setConnection(c); + fields[i].setUseOldNameMetadata(true); + } + + return com.mysql.jdbc.ResultSetImpl.getInstance(c.getCatalog(), fields, + new RowDataStatic(rows), c, null, false); + } + + protected void convertToJdbcFunctionList(String catalog, ResultSet proceduresRs, boolean needsClientFiltering, String db, - Map procedureRowsOrderedByName, int nameIndex) throws SQLException { + List> procedureRows, int nameIndex, + Field[] fields) throws SQLException { while (proceduresRs.next()) { boolean shouldAdd = true; @@ -686,24 +948,52 @@ if (shouldAdd) { String functionName = proceduresRs.getString(nameIndex); - byte[][] rowData = new byte[8][]; - rowData[0] = catalog == null ? null : s2b(catalog); - rowData[1] = null; - rowData[2] = s2b(functionName); - rowData[3] = null; - rowData[4] = null; - rowData[5] = null; - rowData[6] = null; - rowData[7] = s2b(Integer.toString(procedureReturnsResult)); + + byte[][] rowData = null; + + if (fields != null && fields.length == 9) { + + rowData = new byte[9][]; + rowData[0] = catalog == null ? null : s2b(catalog); // PROCEDURE_CAT + rowData[1] = null; // PROCEDURE_SCHEM + rowData[2] = s2b(functionName); // PROCEDURE_NAME + rowData[3] = null; // reserved1 + rowData[4] = null; // reserved2 + rowData[5] = null; // reserved3 + rowData[6] = s2b(proceduresRs.getString("comment")); // REMARKS + rowData[7] = s2b(Integer.toString(procedureReturnsResult)); // PROCEDURE_TYPE + rowData[8] = s2b(functionName); + } else { + + rowData = new byte[6][]; + + rowData[0] = catalog == null ? null : s2b(catalog); // FUNCTION_CAT + rowData[1] = null; // FUNCTION_SCHEM + rowData[2] = s2b(functionName); // FUNCTION_NAME + rowData[3] = s2b(proceduresRs.getString("comment")); // REMARKS + rowData[4] = s2b(Integer.toString(getJDBC4FunctionNoTableConstant())); // FUNCTION_TYPE + rowData[5] = s2b(functionName); // SPECFIC NAME + } - procedureRowsOrderedByName.put(functionName, rowData); + procedureRows.add(new ComparableWrapper(functionName, new ByteArrayRow(rowData, + getExceptionInterceptor()))); } } } - - private void convertToJdbcProcedureList(boolean fromSelect, String catalog, + + /** + * Getter to JDBC4 DatabaseMetaData.functionNoTable constant. + * This method must be overridden by JDBC4 subclasses. This implementation should never be called. + * + * @return 0 + */ + protected int getJDBC4FunctionNoTableConstant() { + return 0; + } + + protected void convertToJdbcProcedureList(boolean fromSelect, String catalog, ResultSet proceduresRs, boolean needsClientFiltering, String db, - Map procedureRowsOrderedByName, int nameIndex) throws SQLException { + List> procedureRows, int nameIndex) throws SQLException { while (proceduresRs.next()) { boolean shouldAdd = true; @@ -721,83 +1011,144 @@ if (shouldAdd) { String procedureName = proceduresRs.getString(nameIndex); - byte[][] rowData = new byte[8][]; + byte[][] rowData = new byte[9][]; rowData[0] = catalog == null ? null : s2b(catalog); rowData[1] = null; rowData[2] = s2b(procedureName); rowData[3] = null; rowData[4] = null; rowData[5] = null; - rowData[6] = null; + rowData[6] = s2b(proceduresRs.getString("comment")); boolean isFunction = fromSelect ? "FUNCTION" .equalsIgnoreCase(proceduresRs.getString("type")) : false; rowData[7] = s2b(isFunction ? Integer .toString(procedureReturnsResult) : Integer - .toString(procedureResultUnknown)); + .toString(procedureNoResult)); - procedureRowsOrderedByName.put(procedureName, rowData); + rowData[8] = s2b(procedureName); + + procedureRows.add(new ComparableWrapper(procedureName, new ByteArrayRow(rowData, + getExceptionInterceptor()))); } } } - private byte[][] convertTypeDescriptorToProcedureRow( - byte[] procNameAsBytes, String paramName, boolean isOutParam, - boolean isInParam, boolean isReturnParam, TypeDescriptor typeDesc) + private ResultSetRow convertTypeDescriptorToProcedureRow( + byte[] procNameAsBytes, byte[] procCatAsBytes, String paramName, boolean isOutParam, + boolean isInParam, boolean isReturnParam, TypeDescriptor typeDesc, + boolean forGetFunctionColumns, + int ordinal) throws SQLException { - byte[][] row = new byte[14][]; - row[0] = null; // PROCEDURE_CAT + byte[][] row = forGetFunctionColumns ? new byte[17][] : new byte[20][]; + row[0] = procCatAsBytes; // PROCEDURE_CAT row[1] = null; // PROCEDURE_SCHEM row[2] = procNameAsBytes; // PROCEDURE/NAME row[3] = s2b(paramName); // COLUMN_NAME - // COLUMN_TYPE - if (isInParam && isOutParam) { - row[4] = s2b(String.valueOf(procedureColumnInOut)); - } else if (isInParam) { - row[4] = s2b(String.valueOf(procedureColumnIn)); - } else if (isOutParam) { - row[4] = s2b(String.valueOf(procedureColumnOut)); - } else if (isReturnParam) { - row[4] = s2b(String.valueOf(procedureColumnReturn)); - } else { - row[4] = s2b(String.valueOf(procedureColumnUnknown)); - } + row[4] = s2b(String.valueOf(getColumnType(isOutParam, isInParam, isReturnParam, forGetFunctionColumns))); // COLUMN_TYPE row[5] = s2b(Short.toString(typeDesc.dataType)); // DATA_TYPE row[6] = s2b(typeDesc.typeName); // TYPE_NAME - row[7] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize - .toString()); // PRECISION - row[8] = s2b(Integer.toString(typeDesc.bufferLength)); // LENGTH - row[9] = typeDesc.decimalDigits == null ? null - : s2b(typeDesc.decimalDigits.toString()); // SCALE + row[7] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize.toString()); // PRECISION + row[8] = row[7]; // LENGTH + row[9] = typeDesc.decimalDigits == null ? null : s2b(typeDesc.decimalDigits.toString()); // SCALE row[10] = s2b(Integer.toString(typeDesc.numPrecRadix)); // RADIX // Map 'column****' to 'procedure****' switch (typeDesc.nullability) { case columnNoNulls: - row[11] = s2b(Integer.toString(procedureNoNulls)); // NULLABLE - + row[11] = s2b(String.valueOf(procedureNoNulls)); // NULLABLE break; case columnNullable: - row[11] = s2b(Integer.toString(procedureNullable)); // NULLABLE - + row[11] = s2b(String.valueOf(procedureNullable)); // NULLABLE break; case columnNullableUnknown: - row[11] = s2b(Integer.toString(procedureNullableUnknown)); // nullable - + row[11] = s2b(String.valueOf(procedureNullableUnknown)); // NULLABLE break; default: - throw SQLError - .createSQLException( - "Internal error while parsing callable statement metadata (unknown nullability value fount)", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Internal error while parsing callable statement metadata (unknown nullability value fount)", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } + row[12] = null; - return row; + + if (forGetFunctionColumns) { + // CHAR_OCTECT_LENGTH + row[13] = null; + + // ORDINAL_POSITION + row[14] = s2b(String.valueOf(ordinal)); + + // IS_NULLABLE + row[15] = s2b(typeDesc.isNullable); + + // SPECIFIC_NAME + row[16] = procNameAsBytes; + } else { + // COLUMN_DEF + row[13] = null; + + // SQL_DATA_TYPE (future use) + row[14] = null; + + // SQL_DATETIME_SUB (future use) + row[15] = null; + + // CHAR_OCTET_LENGTH + row[16] = null; + + // ORDINAL_POSITION + row[17] = s2b(String.valueOf(ordinal)); + + // IS_NULLABLE + row[18] = s2b(typeDesc.isNullable); + + // SPECIFIC_NAME + row[19] = procNameAsBytes; + } + + return new ByteArrayRow(row, getExceptionInterceptor()); } + + /** + * Determines the COLUMN_TYPE information based on parameter type (IN, OUT or INOUT) or function return parameter. + * + * @param isOutParam + * Indicates whether it's an output parameter. + * @param isInParam + * Indicates whether it's an input parameter. + * @param isReturnParam + * Indicates whether it's a function return parameter. + * @param forGetFunctionColumns + * Indicates whether the column belong to a function. This argument is required for JDBC4, in which case + * this method must be overridden to provide the correct functionality. + * + * @return The corresponding COLUMN_TYPE as in java.sql.getProcedureColumns API. + */ + protected int getColumnType(boolean isOutParam, boolean isInParam, boolean isReturnParam, + boolean forGetFunctionColumns) { + if (isInParam && isOutParam) { + return procedureColumnInOut; + } else if (isInParam) { + return procedureColumnIn; + } else if (isOutParam) { + return procedureColumnOut; + } else if (isReturnParam) { + return procedureColumnReturn; + } else { + return procedureColumnUnknown; + } + } + private ExceptionInterceptor exceptionInterceptor; + + protected ExceptionInterceptor getExceptionInterceptor() { + return this.exceptionInterceptor; + } + /** * Does a data definition statement within a transaction force the * transaction to commit? @@ -850,61 +1201,6 @@ } /** - * Finds the end of the parameter declaration from the output of "SHOW - * CREATE PROCEDURE". - * - * @param beginIndex - * should be the index of the procedure body that contains the - * first "(". - * @param procedureDef - * the procedure body - * @param quoteChar - * the identifier quote character in use - * @return the ending index of the parameter declaration, not including the - * closing ")" - * @throws SQLException - * if a parse error occurs. - */ - private int endPositionOfParameterDeclaration(int beginIndex, - String procedureDef, String quoteChar) throws SQLException { - int currentPos = beginIndex + 1; - int parenDepth = 1; // counting the first openParen - - while (parenDepth > 0 && currentPos < procedureDef.length()) { - int closedParenIndex = StringUtils.indexOfIgnoreCaseRespectQuotes( - currentPos, procedureDef, ")", quoteChar.charAt(0), - !this.conn.isNoBackslashEscapesSet()); - - if (closedParenIndex != -1) { - int nextOpenParenIndex = StringUtils - .indexOfIgnoreCaseRespectQuotes(currentPos, - procedureDef, "(", quoteChar.charAt(0), - !this.conn.isNoBackslashEscapesSet()); - - if (nextOpenParenIndex != -1 - && nextOpenParenIndex < closedParenIndex) { - parenDepth++; - currentPos = closedParenIndex + 1; // set after closed - // paren that increases - // depth - } else { - parenDepth--; - currentPos = closedParenIndex; // start search from same - // position - } - } else { - // we should always get closed paren of some sort - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata", - SQLError.SQL_STATE_GENERAL_ERROR); - } - } - - return currentPos; - } - - /** * Extracts foreign key info for one table. * * @param rows @@ -917,139 +1213,122 @@ * @throws SQLException * if a database access error occurs */ - public List extractForeignKeyForTable(ArrayList rows, + public List extractForeignKeyForTable(ArrayList rows, java.sql.ResultSet rs, String catalog) throws SQLException { byte[][] row = new byte[3][]; row[0] = rs.getBytes(1); row[1] = s2b(SUPPORTS_FK); - + String createTableString = rs.getString(2); StringTokenizer lineTokenizer = new StringTokenizer(createTableString, "\n"); StringBuffer commentBuf = new StringBuffer("comment; "); boolean firstTime = true; - + String quoteChar = getIdentifierQuoteString(); - + if (quoteChar == null) { quoteChar = "`"; } - + while (lineTokenizer.hasMoreTokens()) { String line = lineTokenizer.nextToken().trim(); - + String constraintName = null; - + if (StringUtils.startsWithIgnoreCase(line, "CONSTRAINT")) { boolean usingBackTicks = true; - int beginPos = line.indexOf(quoteChar); - + int beginPos = StringUtils.indexOfQuoteDoubleAware(line, quoteChar, 0); + if (beginPos == -1) { beginPos = line.indexOf("\""); usingBackTicks = false; } - + if (beginPos != -1) { int endPos = -1; - + if (usingBackTicks) { - endPos = line.indexOf(quoteChar, beginPos + 1); + endPos = StringUtils.indexOfQuoteDoubleAware(line, quoteChar, beginPos + 1); } else { - endPos = line.indexOf("\"", beginPos + 1); + endPos = StringUtils.indexOfQuoteDoubleAware(line, "\"", beginPos + 1); } - + if (endPos != -1) { constraintName = line.substring(beginPos + 1, endPos); line = line.substring(endPos + 1, line.length()).trim(); } } } - + + if (line.startsWith("FOREIGN KEY")) { if (line.endsWith(",")) { line = line.substring(0, line.length() - 1); } - + char quote = this.quotedId.charAt(0); - + int indexOfFK = line.indexOf("FOREIGN KEY"); - + String localColumnName = null; - String referencedCatalogName = this.quotedId + catalog - + this.quotedId; + String referencedCatalogName = StringUtils.quoteIdentifier(catalog, this.conn.getPedantic()); String referencedTableName = null; String referencedColumnName = null; - + + if (indexOfFK != -1) { int afterFk = indexOfFK + "FOREIGN KEY".length(); - - int indexOfRef = StringUtils - .indexOfIgnoreCaseRespectQuotes(afterFk, line, - "REFERENCES", quote, true); - + + int indexOfRef = StringUtils.indexOfIgnoreCaseRespectQuotes(afterFk, line, "REFERENCES", quote, true); + if (indexOfRef != -1) { - + int indexOfParenOpen = line.indexOf('(', afterFk); - int indexOfParenClose = StringUtils - .indexOfIgnoreCaseRespectQuotes( - indexOfParenOpen, line, ")", quote, - true); - + int indexOfParenClose = StringUtils.indexOfIgnoreCaseRespectQuotes(indexOfParenOpen, line, ")", quote, true); + if (indexOfParenOpen == -1 || indexOfParenClose == -1) { // throw SQLError.createSQLException(); } - - localColumnName = line.substring(indexOfParenOpen + 1, - indexOfParenClose); - + + localColumnName = line.substring(indexOfParenOpen + 1, indexOfParenClose); + int afterRef = indexOfRef + "REFERENCES".length(); - - int referencedColumnBegin = StringUtils - .indexOfIgnoreCaseRespectQuotes(afterRef, line, - "(", quote, true); - + + int referencedColumnBegin = StringUtils.indexOfIgnoreCaseRespectQuotes(afterRef, line, "(", quote, true); + if (referencedColumnBegin != -1) { - referencedTableName = line.substring(afterRef, - referencedColumnBegin); - - int referencedColumnEnd = StringUtils - .indexOfIgnoreCaseRespectQuotes( - referencedColumnBegin + 1, line, - ")", quote, true); - + referencedTableName = line.substring(afterRef, referencedColumnBegin); + + int referencedColumnEnd = StringUtils.indexOfIgnoreCaseRespectQuotes(referencedColumnBegin + 1, line, ")", quote, true); + if (referencedColumnEnd != -1) { - referencedColumnName = line.substring( - referencedColumnBegin + 1, - referencedColumnEnd); + referencedColumnName = line.substring(referencedColumnBegin + 1, referencedColumnEnd); } - - int indexOfCatalogSep = StringUtils - .indexOfIgnoreCaseRespectQuotes(0, - referencedTableName, ".", quote, - true); - + + int indexOfCatalogSep = StringUtils.indexOfIgnoreCaseRespectQuotes(0, referencedTableName, ".", quote, true); + if (indexOfCatalogSep != -1) { - referencedCatalogName = referencedTableName - .substring(0, indexOfCatalogSep); - referencedTableName = referencedTableName - .substring(indexOfCatalogSep + 1); + referencedCatalogName = referencedTableName.substring(0, indexOfCatalogSep); + referencedTableName = referencedTableName.substring(indexOfCatalogSep + 1); } } } } - + + if (!firstTime) { commentBuf.append("; "); } else { firstTime = false; } - + if (constraintName != null) { commentBuf.append(constraintName); } else { commentBuf.append("not_available"); } - + commentBuf.append("("); commentBuf.append(localColumnName); commentBuf.append(") REFER "); @@ -1059,21 +1338,21 @@ commentBuf.append("("); commentBuf.append(referencedColumnName); commentBuf.append(")"); - + int lastParenIndex = line.lastIndexOf(")"); - + if (lastParenIndex != (line.length() - 1)) { - String cascadeOptions = cascadeOptions = line + String cascadeOptions = line .substring(lastParenIndex + 1); commentBuf.append(" "); commentBuf.append(cascadeOptions); } } } - + row[2] = s2b(commentBuf.toString()); - rows.add(row); - + rows.add(new ByteArrayRow(row, getExceptionInterceptor())); + return rows; } @@ -1095,7 +1374,7 @@ */ public ResultSet extractForeignKeyFromCreateTable(String catalog, String tableName) throws SQLException { - ArrayList tableList = new ArrayList(); + ArrayList tableList = new ArrayList(); java.sql.ResultSet rs = null; java.sql.Statement stmt = null; @@ -1117,7 +1396,7 @@ } } - ArrayList rows = new ArrayList(); + ArrayList rows = new ArrayList(); Field[] fields = new Field[3]; fields[0] = new Field("", "Name", Types.CHAR, Integer.MAX_VALUE); fields[1] = new Field("", "Type", Types.CHAR, 255); @@ -1134,12 +1413,12 @@ try { for (int i = 0; i < numTables; i++) { - String tableToExtract = (String) tableList.get(i); - - String query = new StringBuffer("SHOW CREATE TABLE ").append( - quoteChar).append(catalog).append(quoteChar) - .append(".").append(quoteChar).append(tableToExtract) - .append(quoteChar).toString(); + String tableToExtract = tableList.get(i); + + String query = new StringBuffer("SHOW CREATE TABLE ") + .append(StringUtils.quoteIdentifier(catalog, this.conn.getPedantic())).append(".") + .append(StringUtils.quoteIdentifier(tableToExtract, this.conn.getPedantic())).toString(); + try { rs = stmt.executeQuery(query); } catch (SQLException sqlEx) { @@ -1176,65 +1455,6 @@ } /** - * Finds the end of the RETURNS clause for SQL Functions by using any of the - * keywords allowed after the RETURNS clause, or a label. - * - * @param procedureDefn - * the function body containing the definition of the function - * @param quoteChar - * the identifier quote string in use - * @param positionOfReturnKeyword - * the position of "RETRUNS" in the definition - * @return the end of the returns clause - * @throws SQLException - * if a parse error occurs - */ - private int findEndOfReturnsClause(String procedureDefn, String quoteChar, - int positionOfReturnKeyword) throws SQLException { - /* - * characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | - * NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { - * DEFINER | INVOKER } | COMMENT 'string' - */ - - String[] tokens = new String[] { "LANGUAGE", "NOT", "DETERMINISTIC", - "CONTAINS", "NO", "READ", "MODIFIES", "SQL", "COMMENT", "BEGIN", - "RETURN" }; - - int startLookingAt = positionOfReturnKeyword + "RETURNS".length() + 1; - - for (int i = 0; i < tokens.length; i++) { - int endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes( - startLookingAt, procedureDefn, tokens[i], quoteChar - .charAt(0), !this.conn.isNoBackslashEscapesSet()); - - if (endOfReturn != -1) { - return endOfReturn; - } - } - - // Label? - int endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes( - startLookingAt, procedureDefn, ":", quoteChar.charAt(0), - !this.conn.isNoBackslashEscapesSet()); - - if (endOfReturn != -1) { - // seek back until whitespace - for (int i = endOfReturn; i > 0; i--) { - if (Character.isWhitespace(procedureDefn.charAt(i))) { - return i; - } - } - } - - // We can't parse it. - - throw SQLError.createSQLException( - "Internal error when parsing callable statement metadata", - SQLError.SQL_STATE_GENERAL_ERROR); - } - - /** * @see DatabaseMetaData#getAttributes(String, String, String, String) */ public java.sql.ResultSet getAttributes(String arg0, String arg1, @@ -1262,7 +1482,7 @@ fields[19] = new Field("", "SCOPE_TABLE", Types.CHAR, 32); fields[20] = new Field("", "SOURCE_DATA_TYPE", Types.SMALLINT, 32); - return buildResultSet(fields, new ArrayList()); + return buildResultSet(fields, new ArrayList()); } /** @@ -1315,38 +1535,34 @@ throws SQLException { if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } Field[] fields = new Field[8]; fields[0] = new Field("", "SCOPE", Types.SMALLINT, 5); fields[1] = new Field("", "COLUMN_NAME", Types.CHAR, 32); - fields[2] = new Field("", "DATA_TYPE", Types.SMALLINT, 32); + fields[2] = new Field("", "DATA_TYPE", Types.INTEGER, 32); fields[3] = new Field("", "TYPE_NAME", Types.CHAR, 32); fields[4] = new Field("", "COLUMN_SIZE", Types.INTEGER, 10); fields[5] = new Field("", "BUFFER_LENGTH", Types.INTEGER, 10); - fields[6] = new Field("", "DECIMAL_DIGITS", Types.INTEGER, 10); + fields[6] = new Field("", "DECIMAL_DIGITS", Types.SMALLINT, 10); fields[7] = new Field("", "PSEUDO_COLUMN", Types.SMALLINT, 5); - final ArrayList rows = new ArrayList(); + final ArrayList rows = new ArrayList(); final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { ResultSet results = null; try { StringBuffer queryBuf = new StringBuffer( "SHOW COLUMNS FROM "); - queryBuf.append(quotedId); - queryBuf.append(table); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(table, conn.getPedantic())); queryBuf.append(" FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); results = stmt.executeQuery(queryBuf.toString()); @@ -1422,11 +1638,14 @@ java.sql.DatabaseMetaData.bestRowNotPseudo) .getBytes(); - rows.add(rowVal); + rows.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); } } } - + } catch (SQLException sqlEx) { + if (!SQLError.SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND.equals(sqlEx.getSQLState())) { + throw sqlEx; + } } finally { if (results != null) { try { @@ -1484,67 +1703,70 @@ * * @see #getSearchStringEscape */ - private void getCallStmtParameterTypes(String catalog, String procName, - String parameterNamePattern, List resultRows) throws SQLException { + protected void getCallStmtParameterTypes(String catalog, String procName, ProcedureType procType, + String parameterNamePattern, List resultRows) throws SQLException { + getCallStmtParameterTypes(catalog, procName, procType, + parameterNamePattern, resultRows, false); + } + + private void getCallStmtParameterTypes(String catalog, String procName, ProcedureType procType, + String parameterNamePattern, List resultRows, + boolean forGetFunctionColumns) throws SQLException { java.sql.Statement paramRetrievalStmt = null; java.sql.ResultSet paramRetrievalRs = null; if (parameterNamePattern == null) { if (this.conn.getNullNamePatternMatchesAll()) { parameterNamePattern = "%"; } else { - throw SQLError - .createSQLException( - "Parameter/Column name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + throw SQLError.createSQLException( + "Parameter/Column name pattern can not be NULL or empty.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } - byte[] procNameAsBytes = null; - - try { - procNameAsBytes = procName.getBytes("UTF-8"); - } catch (UnsupportedEncodingException ueEx) { - procNameAsBytes = s2b(procName); - } - String quoteChar = getIdentifierQuoteString(); String parameterDef = null; + byte[] procNameAsBytes = null; + byte[] procCatAsBytes = null; + boolean isProcedureInAnsiMode = false; String storageDefnDelims = null; String storageDefnClosures = null; try { paramRetrievalStmt = this.conn.getMetadataSafeStatement(); - - if (this.conn.lowerCaseTableNames() && catalog != null - && catalog.length() != 0) { - // Workaround for bug in server wrt. to + + String oldCatalog = this.conn.getCatalog(); + if (this.conn.lowerCaseTableNames() && catalog != null + && catalog.length() != 0 && oldCatalog != null + && oldCatalog.length() != 0) { + // Workaround for bug in server wrt. to // SHOW CREATE PROCEDURE not respecting // lower-case table names - - String oldCatalog = this.conn.getCatalog(); + ResultSet rs = null; - + try { - this.conn.setCatalog(catalog); + // TODO it isn't right to eliminate all quote chars if catalog name contains them in the middle + this.conn.setCatalog(catalog.replaceAll(quoteChar, "")); rs = paramRetrievalStmt.executeQuery("SELECT DATABASE()"); rs.next(); - + catalog = rs.getString(1); - + } finally { - + this.conn.setCatalog(oldCatalog); - + if (rs != null) { rs.close(); } } } - + if (paramRetrievalStmt.getMaxRows() != 0) { paramRetrievalStmt.setMaxRows(0); } @@ -1568,6 +1790,29 @@ dbName = catalog; } + // Moved from above so that procName is *without* database as expected + // by the rest of code + // Removing QuoteChar to get output as it was before PROC_CAT fixes + String tmpProcName = procName; + tmpProcName = tmpProcName.replaceAll(quoteChar, ""); + try { + procNameAsBytes = StringUtils.getBytes(tmpProcName, "UTF-8"); + } catch (UnsupportedEncodingException ueEx) { + procNameAsBytes = s2b(tmpProcName); + + // Set all fields to connection encoding + } + + tmpProcName = dbName; + tmpProcName = tmpProcName.replaceAll(quoteChar, ""); + try { + procCatAsBytes = StringUtils.getBytes(tmpProcName, "UTF-8"); + } catch (UnsupportedEncodingException ueEx) { + procCatAsBytes = s2b(tmpProcName); + + // Set all fields to connection encoding + } + StringBuffer procNameBuf = new StringBuffer(); if (dbName != null) { @@ -1596,32 +1841,24 @@ procNameBuf.append(quoteChar); } - boolean parsingFunction = false; - - try { - paramRetrievalRs = paramRetrievalStmt - .executeQuery("SHOW CREATE PROCEDURE " - + procNameBuf.toString()); - parsingFunction = false; - } catch (SQLException sqlEx) { - paramRetrievalRs = paramRetrievalStmt - .executeQuery("SHOW CREATE FUNCTION " - + procNameBuf.toString()); - parsingFunction = true; + String fieldName = null; + if (procType == PROCEDURE) { + paramRetrievalRs = paramRetrievalStmt.executeQuery("SHOW CREATE PROCEDURE " + procNameBuf.toString()); + fieldName = "Create Procedure"; + } else { + paramRetrievalRs = paramRetrievalStmt.executeQuery("SHOW CREATE FUNCTION " + procNameBuf.toString()); + fieldName = "Create Function"; } if (paramRetrievalRs.next()) { - String procedureDef = parsingFunction ? paramRetrievalRs - .getString("Create Function") : paramRetrievalRs - .getString("Create Procedure"); - - if (procedureDef == null || procedureDef.length() == 0) { - throw SQLError - .createSQLException( - "User does not have access to metadata required to determine " - + "stored procedure parameter types. If rights can not be granted, configure connection with \"noAccessToProcedureBodies=true\" " - + "to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.", - SQLError.SQL_STATE_GENERAL_ERROR); + String procedureDef = paramRetrievalRs.getString(fieldName); + + if (!this.conn.getNoAccessToProcedureBodies() && + (procedureDef == null || procedureDef.length() == 0)) { + throw SQLError.createSQLException("User does not have access to metadata required to determine " + + "stored procedure parameter types. If rights can not be granted, configure connection with \"noAccessToProcedureBodies=true\" " + + "to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } try { @@ -1639,63 +1876,66 @@ storageDefnDelims = "(" + identifierMarkers; storageDefnClosures = ")" + identifierMarkers; - // sanitize/normalize by stripping out comments - procedureDef = StringUtils.stripComments(procedureDef, - identifierAndStringMarkers, identifierAndStringMarkers, true, false, true, true); - - int openParenIndex = StringUtils - .indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(", - quoteChar.charAt(0), !this.conn - .isNoBackslashEscapesSet()); - int endOfParamDeclarationIndex = 0; + if (procedureDef != null && procedureDef.length() != 0) { + // sanitize/normalize by stripping out comments + procedureDef = StringUtils.stripComments(procedureDef, + identifierAndStringMarkers, identifierAndStringMarkers, true, false, true, true); + + int openParenIndex = StringUtils + .indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(", + quoteChar.charAt(0), !this.conn + .isNoBackslashEscapesSet()); + int endOfParamDeclarationIndex = 0; - endOfParamDeclarationIndex = endPositionOfParameterDeclaration( - openParenIndex, procedureDef, quoteChar); + endOfParamDeclarationIndex = endPositionOfParameterDeclaration( + openParenIndex, procedureDef, quoteChar); - if (parsingFunction) { + if (procType == FUNCTION) { - // Grab the return column since it needs - // to go first in the output result set - int returnsIndex = StringUtils - .indexOfIgnoreCaseRespectQuotes(0, procedureDef, - " RETURNS ", quoteChar.charAt(0), - !this.conn.isNoBackslashEscapesSet()); + // Grab the return column since it needs + // to go first in the output result set + int returnsIndex = StringUtils + .indexOfIgnoreCaseRespectQuotes(0, procedureDef, + " RETURNS ", quoteChar.charAt(0), + !this.conn.isNoBackslashEscapesSet()); - int endReturnsDef = findEndOfReturnsClause(procedureDef, - quoteChar, returnsIndex); + int endReturnsDef = findEndOfReturnsClause(procedureDef, + quoteChar, returnsIndex); - // Trim off whitespace after "RETURNS" - - int declarationStart = returnsIndex + "RETURNS ".length(); - - while (declarationStart < procedureDef.length()) { - if (Character.isWhitespace(procedureDef.charAt(declarationStart))) { - declarationStart++; - } else { - break; + // Trim off whitespace after "RETURNS" + + int declarationStart = returnsIndex + "RETURNS ".length(); + + while (declarationStart < procedureDef.length()) { + if (Character.isWhitespace(procedureDef.charAt(declarationStart))) { + declarationStart++; + } else { + break; + } } + + String returnsDefn = procedureDef.substring(declarationStart, endReturnsDef).trim(); + TypeDescriptor returnDescriptor = new TypeDescriptor( + returnsDefn, "YES"); + + resultRows.add(convertTypeDescriptorToProcedureRow( + procNameAsBytes, procCatAsBytes, "", false, false, true, + returnDescriptor, forGetFunctionColumns, 0)); } - - String returnsDefn = procedureDef.substring(declarationStart, endReturnsDef).trim(); - TypeDescriptor returnDescriptor = new TypeDescriptor( - returnsDefn, null); - resultRows.add(convertTypeDescriptorToProcedureRow( - procNameAsBytes, "", false, false, true, - returnDescriptor)); - } + if ((openParenIndex == -1) + || (endOfParamDeclarationIndex == -1)) { + // parse error? + throw SQLError + .createSQLException( + "Internal error when parsing callable statement metadata", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } - if ((openParenIndex == -1) - || (endOfParamDeclarationIndex == -1)) { - // parse error? - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata", - SQLError.SQL_STATE_GENERAL_ERROR); + parameterDef = procedureDef.substring(openParenIndex + 1, + endOfParamDeclarationIndex); } - - parameterDef = procedureDef.substring(openParenIndex + 1, - endOfParamDeclarationIndex); + } } finally { SQLException sqlExRethrow = null; @@ -1726,20 +1966,23 @@ } if (parameterDef != null) { - - List parseList = StringUtils.split(parameterDef, ",", + int ordinal = 1; + + List parseList = StringUtils.split(parameterDef, ",", storageDefnDelims, storageDefnClosures, true); int parseListLen = parseList.size(); for (int i = 0; i < parseListLen; i++) { - String declaration = (String) parseList.get(i); + String declaration = parseList.get(i); if (declaration.trim().length() == 0) { - break; // no parameters actually declared, but whitespace - // spans lines + break; // no parameters actually declared, but whitespace spans lines } - + + // Bug#52167, tokenizer will break if declaration + // contains special characters like \n + declaration = declaration.replaceAll("[\\t\\n\\x0B\\f\\r]", " "); StringTokenizer declarationTok = new StringTokenizer( declaration, " \t"); @@ -1756,10 +1999,9 @@ if (declarationTok.hasMoreTokens()) { paramName = declarationTok.nextToken(); } else { - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata (missing parameter name)", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Internal error when parsing callable statement metadata (missing parameter name)", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } else if (possibleParamName.equalsIgnoreCase("INOUT")) { isOutParam = true; @@ -1768,10 +2010,9 @@ if (declarationTok.hasMoreTokens()) { paramName = declarationTok.nextToken(); } else { - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata (missing parameter name)", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Internal error when parsing callable statement metadata (missing parameter name)", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } else if (possibleParamName.equalsIgnoreCase("IN")) { isOutParam = false; @@ -1780,10 +2021,9 @@ if (declarationTok.hasMoreTokens()) { paramName = declarationTok.nextToken(); } else { - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata (missing parameter name)", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Internal error when parsing callable statement metadata (missing parameter name)", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } else { isOutParam = false; @@ -1805,34 +2045,33 @@ String typeInfo = typeInfoBuf.toString(); - typeDesc = new TypeDescriptor(typeInfo, null); + typeDesc = new TypeDescriptor(typeInfo, "YES"); } else { - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata (missing parameter type)", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Internal error when parsing callable statement metadata (missing parameter type)", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } if ((paramName.startsWith("`") && paramName.endsWith("`")) || (isProcedureInAnsiMode && paramName.startsWith("\"") && paramName.endsWith("\""))) { paramName = paramName.substring(1, paramName.length() - 1); } - + int wildCompareRes = StringUtils.wildCompare(paramName, parameterNamePattern); if (wildCompareRes != StringUtils.WILD_COMPARE_NO_MATCH) { - byte[][] row = convertTypeDescriptorToProcedureRow( - procNameAsBytes, paramName, isOutParam, - isInParam, false, typeDesc); + ResultSetRow row = convertTypeDescriptorToProcedureRow( + procNameAsBytes, procCatAsBytes, paramName, isOutParam, + isInParam, false, typeDesc, forGetFunctionColumns, + ordinal++); resultRows.add(row); } } else { - throw SQLError - .createSQLException( - "Internal error when parsing callable statement metadata (unknown output from 'SHOW CREATE PROCEDURE')", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Internal error when parsing callable statement metadata (unknown output from 'SHOW CREATE PROCEDURE')", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } } else { @@ -1841,8 +2080,129 @@ // exist, is it an error.... } } + /** + * Finds the end of the parameter declaration from the output of "SHOW + * CREATE PROCEDURE". + * + * @param beginIndex + * should be the index of the procedure body that contains the + * first "(". + * @param procedureDef + * the procedure body + * @param quoteChar + * the identifier quote character in use + * @return the ending index of the parameter declaration, not including the + * closing ")" + * @throws SQLException + * if a parse error occurs. + */ + private int endPositionOfParameterDeclaration(int beginIndex, + String procedureDef, String quoteChar) throws SQLException { + int currentPos = beginIndex + 1; + int parenDepth = 1; // counting the first openParen + while (parenDepth > 0 && currentPos < procedureDef.length()) { + int closedParenIndex = StringUtils.indexOfIgnoreCaseRespectQuotes( + currentPos, procedureDef, ")", quoteChar.charAt(0), + !this.conn.isNoBackslashEscapesSet()); + + if (closedParenIndex != -1) { + int nextOpenParenIndex = StringUtils + .indexOfIgnoreCaseRespectQuotes(currentPos, + procedureDef, "(", quoteChar.charAt(0), + !this.conn.isNoBackslashEscapesSet()); + + if (nextOpenParenIndex != -1 + && nextOpenParenIndex < closedParenIndex) { + parenDepth++; + currentPos = closedParenIndex + 1; // set after closed + // paren that increases + // depth + } else { + parenDepth--; + currentPos = closedParenIndex; // start search from same + // position + } + } else { + // we should always get closed paren of some sort + throw SQLError + .createSQLException( + "Internal error when parsing callable statement metadata", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + return currentPos; + } + /** + * Finds the end of the RETURNS clause for SQL Functions by using any of the + * keywords allowed after the RETURNS clause, or a label. + * + * @param procedureDefn + * the function body containing the definition of the function + * @param quoteChar + * the identifier quote string in use + * @param positionOfReturnKeyword + * the position of "RETRUNS" in the definition + * @return the end of the returns clause + * @throws SQLException + * if a parse error occurs + */ + private int findEndOfReturnsClause(String procedureDefn, String quoteChar, + int positionOfReturnKeyword) throws SQLException { + /* + * characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | + * NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { + * DEFINER | INVOKER } | COMMENT 'string' + */ + + String[] tokens = new String[] { "LANGUAGE", "NOT", "DETERMINISTIC", + "CONTAINS", "NO", "READ", "MODIFIES", "SQL", "COMMENT", "BEGIN", + "RETURN" }; + + int startLookingAt = positionOfReturnKeyword + "RETURNS".length() + 1; + + int endOfReturn = -1; + + for (int i = 0; i < tokens.length; i++) { + int nextEndOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes( + startLookingAt, procedureDefn, tokens[i], quoteChar + .charAt(0), !this.conn.isNoBackslashEscapesSet()); + + if (nextEndOfReturn != -1) { + if (endOfReturn == -1 || (nextEndOfReturn < endOfReturn)) { + endOfReturn = nextEndOfReturn; + } + } + } + + if (endOfReturn != -1) { + return endOfReturn; + } + + // Label? + endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes( + startLookingAt, procedureDefn, ":", quoteChar.charAt(0), + !this.conn.isNoBackslashEscapesSet()); + + if (endOfReturn != -1) { + // seek back until whitespace + for (int i = endOfReturn; i > 0; i--) { + if (Character.isWhitespace(procedureDefn.charAt(i))) { + return i; + } + } + } + + // We can't parse it. + + throw SQLError.createSQLException( + "Internal error when parsing callable statement metadata", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + + /** * Parses the cascade option string and returns the DBMD constant that * represents it (for deletes) * @@ -1900,25 +2260,30 @@ return java.sql.DatabaseMetaData.importedKeyNoAction; } - protected IteratorWithCleanup getCatalogIterator(String catalogSpec) + protected IteratorWithCleanup getCatalogIterator(String catalogSpec) throws SQLException { - IteratorWithCleanup allCatalogsIter; + IteratorWithCleanup allCatalogsIter; if (catalogSpec != null) { if (!catalogSpec.equals("")) { - allCatalogsIter = new SingleStringIterator(catalogSpec); + if (conn.getPedantic()) { + allCatalogsIter = new SingleStringIterator(catalogSpec); + } else { + allCatalogsIter = new SingleStringIterator(StringUtils.unQuoteIdentifier(catalogSpec, this.conn.useAnsiQuotedIdentifiers())); + } } else { // legacy mode of operation allCatalogsIter = new SingleStringIterator(this.database); } } else if (this.conn.getNullCatalogMeansCurrent()) { + allCatalogsIter = new SingleStringIterator(this.database); } else { allCatalogsIter = new ResultSetIterator(getCatalogs(), 1); } return allCatalogsIter; } - + /** * Get the catalog names available in this database. The results are ordered * by catalog name. @@ -1948,12 +2313,12 @@ fields[0] = new Field("", "TABLE_CAT", Types.VARCHAR, resultsMD .getColumnDisplaySize(1)); - ArrayList tuples = new ArrayList(); + ArrayList tuples = new ArrayList(); while (results.next()) { byte[][] rowVal = new byte[1][]; rowVal[0] = results.getBytes(1); - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); } return buildResultSet(fields, tuples); @@ -2078,7 +2443,7 @@ Statement stmt = null; ResultSet results = null; - ArrayList grantRows = new ArrayList(); + ArrayList grantRows = new ArrayList(); try { stmt = this.conn.createStatement(); @@ -2127,7 +2492,7 @@ tuple[5] = s2b(fullUser.toString()); tuple[6] = s2b(privilege); tuple[7] = null; - grantRows.add(tuple); + grantRows.add(new ByteArrayRow(tuple, getExceptionInterceptor())); } } } @@ -2223,55 +2588,30 @@ } else { throw SQLError.createSQLException( "Column name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } final String colPattern = columnNamePattern; - Field[] fields = new Field[23]; - fields[0] = new Field("", "TABLE_CAT", Types.CHAR, 255); - fields[1] = new Field("", "TABLE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "TABLE_NAME", Types.CHAR, 255); - fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 32); - fields[4] = new Field("", "DATA_TYPE", Types.SMALLINT, 5); - fields[5] = new Field("", "TYPE_NAME", Types.CHAR, 16); - fields[6] = new Field("", "COLUMN_SIZE", Types.INTEGER, Integer - .toString(Integer.MAX_VALUE).length()); - fields[7] = new Field("", "BUFFER_LENGTH", Types.INTEGER, 10); - fields[8] = new Field("", "DECIMAL_DIGITS", Types.INTEGER, 10); - fields[9] = new Field("", "NUM_PREC_RADIX", Types.INTEGER, 10); - fields[10] = new Field("", "NULLABLE", Types.INTEGER, 10); - fields[11] = new Field("", "REMARKS", Types.CHAR, 0); - fields[12] = new Field("", "COLUMN_DEF", Types.CHAR, 0); - fields[13] = new Field("", "SQL_DATA_TYPE", Types.INTEGER, 10); - fields[14] = new Field("", "SQL_DATETIME_SUB", Types.INTEGER, 10); - fields[15] = new Field("", "CHAR_OCTET_LENGTH", Types.INTEGER, Integer - .toString(Integer.MAX_VALUE).length()); - fields[16] = new Field("", "ORDINAL_POSITION", Types.INTEGER, 10); - fields[17] = new Field("", "IS_NULLABLE", Types.CHAR, 3); - fields[18] = new Field("", "SCOPE_CATALOG", Types.CHAR, 255); - fields[19] = new Field("", "SCOPE_SCHEMA", Types.CHAR, 255); - fields[20] = new Field("", "SCOPE_TABLE", Types.CHAR, 255); - fields[21] = new Field("", "SOURCE_DATA_TYPE", Types.SMALLINT, 10); - fields[22] = new Field("", "IS_AUTOINCREMENT", Types.CHAR, 3); + Field[] fields = createColumnsFields(); - final ArrayList rows = new ArrayList(); + final ArrayList rows = new ArrayList(); final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { - ArrayList tableNameList = new ArrayList(); + ArrayList tableNameList = new ArrayList(); if (tableNamePattern == null) { // Select from all tables java.sql.ResultSet tables = null; try { - tables = getTables(catalog, schemaPattern, "%", + tables = getTables(catalogStr, schemaPattern, "%", new String[0]); while (tables.next()) { @@ -2295,7 +2635,7 @@ java.sql.ResultSet tables = null; try { - tables = getTables(catalog, schemaPattern, + tables = getTables(catalogStr, schemaPattern, tableNamePattern, new String[0]); while (tables.next()) { @@ -2317,11 +2657,8 @@ } } - java.util.Iterator tableNames = tableNameList.iterator(); - - while (tableNames.hasNext()) { - String tableName = (String) tableNames.next(); - + for (String tableName : tableNameList) { + ResultSet results = null; try { @@ -2332,13 +2669,9 @@ } queryBuf.append("COLUMNS FROM "); - queryBuf.append(quotedId); - queryBuf.append(tableName); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(tableName, conn.getPedantic())); queryBuf.append(" FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); queryBuf.append(" LIKE '"); queryBuf.append(colPattern); queryBuf.append("'"); @@ -2349,7 +2682,7 @@ // this, so we do it the 'hard' way...Once _SYSTEM // tables are in, this should be much easier boolean fixUpOrdinalsRequired = false; - Map ordinalFixUpMap = null; + Map ordinalFixUpMap = null; if (!colPattern.equals("%")) { fixUpOrdinalsRequired = true; @@ -2362,19 +2695,14 @@ } fullColumnQueryBuf.append("COLUMNS FROM "); - fullColumnQueryBuf.append(quotedId); - fullColumnQueryBuf.append(tableName); - fullColumnQueryBuf.append(quotedId); + fullColumnQueryBuf.append(StringUtils.quoteIdentifier(tableName, conn.getPedantic())); fullColumnQueryBuf.append(" FROM "); - fullColumnQueryBuf.append(quotedId); - fullColumnQueryBuf - .append(catalogStr.toString()); - fullColumnQueryBuf.append(quotedId); + fullColumnQueryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); results = stmt.executeQuery(fullColumnQueryBuf .toString()); - ordinalFixUpMap = new HashMap(); + ordinalFixUpMap = new HashMap(); int fullOrdinalPos = 1; @@ -2383,7 +2711,7 @@ .getString("Field"); ordinalFixUpMap.put(fullOrdColName, - new Integer(fullOrdinalPos++)); + Integer.valueOf(fullOrdinalPos++)); } } @@ -2392,8 +2720,8 @@ int ordPos = 1; while (results.next()) { - byte[][] rowVal = new byte[23][]; - rowVal[0] = s2b(catalog); // TABLE_CAT + byte[][] rowVal = new byte[24][]; + rowVal[0] = s2b(catalogStr); // TABLE_CAT rowVal[1] = null; // TABLE_SCHEM (No schemas // in MySQL) @@ -2410,12 +2738,29 @@ // DATA_TYPE (jdbc) rowVal[5] = s2b(typeDesc.typeName); // TYPE_NAME // (native) - rowVal[6] = typeDesc.columnSize == null ? null - : s2b(typeDesc.columnSize.toString()); - rowVal[7] = s2b(Integer - .toString(typeDesc.bufferLength)); - rowVal[8] = typeDesc.decimalDigits == null ? null - : s2b(typeDesc.decimalDigits.toString()); + if (typeDesc.columnSize == null) { + rowVal[6] = null; + } else { + String collation = results.getString("Collation"); + int mbminlen = 1; + if (collation != null && ( + "TEXT".equals(typeDesc.typeName) || + "TINYTEXT".equals(typeDesc.typeName) || + "MEDIUMTEXT".equals(typeDesc.typeName) + )) { + if ( collation.indexOf("ucs2") > -1 || + collation.indexOf("utf16") > -1) { + mbminlen = 2; + } else if (collation.indexOf("utf32") > -1) { + mbminlen = 4; + } + } + rowVal[6] = mbminlen == 1 ? + s2b(typeDesc.columnSize.toString()) : + s2b(((Integer)(typeDesc.columnSize / mbminlen)).toString()); + } + rowVal[7] = s2b(Integer.toString(typeDesc.bufferLength)); + rowVal[8] = typeDesc.decimalDigits == null ? null : s2b(typeDesc.decimalDigits.toString()); rowVal[9] = s2b(Integer .toString(typeDesc.numPrecRadix)); rowVal[10] = s2b(Integer @@ -2444,15 +2789,11 @@ rowVal[13] = new byte[] { (byte) '0' }; // SQL_DATA_TYPE rowVal[14] = new byte[] { (byte) '0' }; // SQL_DATE_TIME_SUB - - if (StringUtils.indexOfIgnoreCase( - typeDesc.typeName, "CHAR") != -1 - || StringUtils.indexOfIgnoreCase( - typeDesc.typeName, "BLOB") != -1 - || StringUtils.indexOfIgnoreCase( - typeDesc.typeName, "TEXT") != -1 - || StringUtils.indexOfIgnoreCase( - typeDesc.typeName, "BINARY") != -1) { + + if (StringUtils.indexOfIgnoreCase(typeDesc.typeName, "CHAR") != -1 || + StringUtils.indexOfIgnoreCase(typeDesc.typeName, "BLOB") != -1 || + StringUtils.indexOfIgnoreCase(typeDesc.typeName, "TEXT") != -1 || + StringUtils.indexOfIgnoreCase(typeDesc.typeName, "BINARY") != -1) { rowVal[15] = rowVal[6]; // CHAR_OCTET_LENGTH } else { rowVal[15] = null; @@ -2465,17 +2806,16 @@ } else { String origColName = results .getString("Field"); - Integer realOrdinal = (Integer) ordinalFixUpMap + Integer realOrdinal = ordinalFixUpMap .get(origColName); if (realOrdinal != null) { rowVal[16] = realOrdinal.toString() .getBytes(); } else { - throw SQLError - .createSQLException( - "Can not find column in full column list to determine true ordinal position.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Can not find column in full column list to determine true ordinal position.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } @@ -2497,8 +2837,9 @@ "auto_increment") != -1 ? "YES" : "NO"); } + rowVal[23] = s2b(""); - rows.add(rowVal); + rows.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); } } finally { if (results != null) { @@ -2525,6 +2866,37 @@ return results; } + protected Field[] createColumnsFields() { + Field[] fields = new Field[24]; + fields[0] = new Field("", "TABLE_CAT", Types.CHAR, 255); + fields[1] = new Field("", "TABLE_SCHEM", Types.CHAR, 0); + fields[2] = new Field("", "TABLE_NAME", Types.CHAR, 255); + fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 32); + fields[4] = new Field("", "DATA_TYPE", Types.INTEGER, 5); + fields[5] = new Field("", "TYPE_NAME", Types.CHAR, 16); + fields[6] = new Field("", "COLUMN_SIZE", Types.INTEGER, Integer + .toString(Integer.MAX_VALUE).length()); + fields[7] = new Field("", "BUFFER_LENGTH", Types.INTEGER, 10); + fields[8] = new Field("", "DECIMAL_DIGITS", Types.INTEGER, 10); + fields[9] = new Field("", "NUM_PREC_RADIX", Types.INTEGER, 10); + fields[10] = new Field("", "NULLABLE", Types.INTEGER, 10); + fields[11] = new Field("", "REMARKS", Types.CHAR, 0); + fields[12] = new Field("", "COLUMN_DEF", Types.CHAR, 0); + fields[13] = new Field("", "SQL_DATA_TYPE", Types.INTEGER, 10); + fields[14] = new Field("", "SQL_DATETIME_SUB", Types.INTEGER, 10); + fields[15] = new Field("", "CHAR_OCTET_LENGTH", Types.INTEGER, Integer + .toString(Integer.MAX_VALUE).length()); + fields[16] = new Field("", "ORDINAL_POSITION", Types.INTEGER, 10); + fields[17] = new Field("", "IS_NULLABLE", Types.CHAR, 3); + fields[18] = new Field("", "SCOPE_CATALOG", Types.CHAR, 255); + fields[19] = new Field("", "SCOPE_SCHEMA", Types.CHAR, 255); + fields[20] = new Field("", "SCOPE_TABLE", Types.CHAR, 255); + fields[21] = new Field("", "SOURCE_DATA_TYPE", Types.SMALLINT, 10); + fields[22] = new Field("", "IS_AUTOINCREMENT", Types.CHAR, 3); // JDBC 4 + fields[23] = new Field("", "IS_GENERATEDCOLUMN", Types.CHAR, 3); // JDBC 4.1 + return fields; + } + /** * JDBC 2.0 Return the connection that produced this metadata object. * @@ -2609,35 +2981,21 @@ final String foreignTable) throws SQLException { if (primaryTable == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - Field[] fields = new Field[14]; - fields[0] = new Field("", "PKTABLE_CAT", Types.CHAR, 255); - fields[1] = new Field("", "PKTABLE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PKTABLE_NAME", Types.CHAR, 255); - fields[3] = new Field("", "PKCOLUMN_NAME", Types.CHAR, 32); - fields[4] = new Field("", "FKTABLE_CAT", Types.CHAR, 255); - fields[5] = new Field("", "FKTABLE_SCHEM", Types.CHAR, 0); - fields[6] = new Field("", "FKTABLE_NAME", Types.CHAR, 255); - fields[7] = new Field("", "FKCOLUMN_NAME", Types.CHAR, 32); - fields[8] = new Field("", "KEY_SEQ", Types.SMALLINT, 2); - fields[9] = new Field("", "UPDATE_RULE", Types.SMALLINT, 2); - fields[10] = new Field("", "DELETE_RULE", Types.SMALLINT, 2); - fields[11] = new Field("", "FK_NAME", Types.CHAR, 0); - fields[12] = new Field("", "PK_NAME", Types.CHAR, 0); - fields[13] = new Field("", "DEFERRABILITY", Types.INTEGER, 2); + Field[] fields = createFkMetadataFields(); - final ArrayList tuples = new ArrayList(); + final ArrayList tuples = new ArrayList(); if (this.conn.versionMeetsMinimum(3, 23, 0)) { final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(foreignCatalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(foreignCatalog)) { + void forEach(String catalogStr) throws SQLException { ResultSet fkresults = null; @@ -2648,13 +3006,11 @@ */ if (conn.versionMeetsMinimum(3, 23, 50)) { fkresults = extractForeignKeyFromCreateTable( - catalogStr.toString(), null); + catalogStr, null); } else { StringBuffer queryBuf = new StringBuffer( "SHOW TABLE STATUS FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); fkresults = stmt.executeQuery(queryBuf .toString()); @@ -2696,14 +3052,15 @@ int keySeq = 0; - Iterator referencingColumns = parsedInfo.localColumnsList + Iterator referencingColumns = parsedInfo.localColumnsList .iterator(); - Iterator referencedColumns = parsedInfo.referencedColumnsList + Iterator referencedColumns = parsedInfo.referencedColumnsList .iterator(); while (referencingColumns.hasNext()) { - String referencingColumn = removeQuotedId(referencingColumns - .next().toString()); + String referencingColumn = StringUtils.unQuoteIdentifier( + referencingColumns.next(), + conn.useAnsiQuotedIdentifiers()); // one tuple for each table // between @@ -2738,8 +3095,9 @@ } tuple[2] = s2b(parsedInfo.referencedTable); // PKTABLE_NAME - tuple[3] = s2b(removeQuotedId(referencedColumns - .next().toString())); // PKCOLUMN_NAME + tuple[3] = s2b(StringUtils.unQuoteIdentifier( + referencedColumns.next(), + conn.useAnsiQuotedIdentifiers())); // PKCOLUMN_NAME tuple[8] = Integer.toString( keySeq).getBytes(); // KEY_SEQ @@ -2755,7 +3113,7 @@ .toString( java.sql.DatabaseMetaData.importedKeyNotDeferrable) .getBytes(); - tuples.add(tuple); + tuples.add(new ByteArrayRow(tuple, getExceptionInterceptor())); keySeq++; } } @@ -2789,6 +3147,25 @@ return results; } + protected Field[] createFkMetadataFields() { + Field[] fields = new Field[14]; + fields[0] = new Field("", "PKTABLE_CAT", Types.CHAR, 255); + fields[1] = new Field("", "PKTABLE_SCHEM", Types.CHAR, 0); + fields[2] = new Field("", "PKTABLE_NAME", Types.CHAR, 255); + fields[3] = new Field("", "PKCOLUMN_NAME", Types.CHAR, 32); + fields[4] = new Field("", "FKTABLE_CAT", Types.CHAR, 255); + fields[5] = new Field("", "FKTABLE_SCHEM", Types.CHAR, 0); + fields[6] = new Field("", "FKTABLE_NAME", Types.CHAR, 255); + fields[7] = new Field("", "FKCOLUMN_NAME", Types.CHAR, 32); + fields[8] = new Field("", "KEY_SEQ", Types.SMALLINT, 2); + fields[9] = new Field("", "UPDATE_RULE", Types.SMALLINT, 2); + fields[10] = new Field("", "DELETE_RULE", Types.SMALLINT, 2); + fields[11] = new Field("", "FK_NAME", Types.CHAR, 0); + fields[12] = new Field("", "PK_NAME", Types.CHAR, 0); + fields[13] = new Field("", "DEFERRABILITY", Types.SMALLINT, 2); + return fields; + } + /** * @see DatabaseMetaData#getDatabaseMajorVersion() */ @@ -2868,7 +3245,7 @@ * DOCUMENT ME! */ public String getDriverName() throws SQLException { - return "MySQL-AB JDBC Driver"; + return NonRegisteringDriver.NAME; } /** @@ -2945,35 +3322,21 @@ final String table) throws SQLException { if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - Field[] fields = new Field[14]; - fields[0] = new Field("", "PKTABLE_CAT", Types.CHAR, 255); - fields[1] = new Field("", "PKTABLE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PKTABLE_NAME", Types.CHAR, 255); - fields[3] = new Field("", "PKCOLUMN_NAME", Types.CHAR, 32); - fields[4] = new Field("", "FKTABLE_CAT", Types.CHAR, 255); - fields[5] = new Field("", "FKTABLE_SCHEM", Types.CHAR, 0); - fields[6] = new Field("", "FKTABLE_NAME", Types.CHAR, 255); - fields[7] = new Field("", "FKCOLUMN_NAME", Types.CHAR, 32); - fields[8] = new Field("", "KEY_SEQ", Types.SMALLINT, 2); - fields[9] = new Field("", "UPDATE_RULE", Types.SMALLINT, 2); - fields[10] = new Field("", "DELETE_RULE", Types.SMALLINT, 2); - fields[11] = new Field("", "FK_NAME", Types.CHAR, 255); - fields[12] = new Field("", "PK_NAME", Types.CHAR, 0); - fields[13] = new Field("", "DEFERRABILITY", Types.INTEGER, 2); + Field[] fields = createFkMetadataFields(); - final ArrayList rows = new ArrayList(); + final ArrayList rows = new ArrayList(); if (this.conn.versionMeetsMinimum(3, 23, 0)) { final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { ResultSet fkresults = null; try { @@ -2985,13 +3348,11 @@ // we can use 'SHOW CREATE TABLE' fkresults = extractForeignKeyFromCreateTable( - catalogStr.toString(), null); + catalogStr, null); } else { StringBuffer queryBuf = new StringBuffer( "SHOW TABLE STATUS FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); fkresults = stmt.executeQuery(queryBuf .toString()); @@ -3028,7 +3389,7 @@ String keys = commentTokens .nextToken(); getExportKeyResults( - catalogStr.toString(), + catalogStr, tableNameWithCase, keys, rows, @@ -3084,8 +3445,8 @@ * @throws SQLException * if a database access error occurs */ - private void getExportKeyResults(String catalog, String exportingTable, - String keysComment, List tuples, String fkTableName) + protected void getExportKeyResults(String catalog, String exportingTable, + String keysComment, List tuples, String fkTableName) throws SQLException { getResultsImpl(catalog, exportingTable, keysComment, tuples, fkTableName, true); @@ -3112,7 +3473,7 @@ * the comment from 'SHOW TABLE STATUS' * @return int[] [0] = delete action, [1] = update action */ - private int[] getForeignKeyActions(String commentString) { + protected int[] getForeignKeyActions(String commentString) { int[] actions = new int[] { java.sql.DatabaseMetaData.importedKeyNoAction, java.sql.DatabaseMetaData.importedKeyNoAction }; @@ -3214,35 +3575,21 @@ final String table) throws SQLException { if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - Field[] fields = new Field[14]; - fields[0] = new Field("", "PKTABLE_CAT", Types.CHAR, 255); - fields[1] = new Field("", "PKTABLE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PKTABLE_NAME", Types.CHAR, 255); - fields[3] = new Field("", "PKCOLUMN_NAME", Types.CHAR, 32); - fields[4] = new Field("", "FKTABLE_CAT", Types.CHAR, 255); - fields[5] = new Field("", "FKTABLE_SCHEM", Types.CHAR, 0); - fields[6] = new Field("", "FKTABLE_NAME", Types.CHAR, 255); - fields[7] = new Field("", "FKCOLUMN_NAME", Types.CHAR, 32); - fields[8] = new Field("", "KEY_SEQ", Types.SMALLINT, 2); - fields[9] = new Field("", "UPDATE_RULE", Types.SMALLINT, 2); - fields[10] = new Field("", "DELETE_RULE", Types.SMALLINT, 2); - fields[11] = new Field("", "FK_NAME", Types.CHAR, 255); - fields[12] = new Field("", "PK_NAME", Types.CHAR, 0); - fields[13] = new Field("", "DEFERRABILITY", Types.INTEGER, 2); + Field[] fields = createFkMetadataFields(); + + final ArrayList rows = new ArrayList(); - final ArrayList rows = new ArrayList(); - if (this.conn.versionMeetsMinimum(3, 23, 0)) { final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { ResultSet fkresults = null; try { @@ -3254,14 +3601,12 @@ // we can use 'SHOW CREATE TABLE' fkresults = extractForeignKeyFromCreateTable( - catalogStr.toString(), table); + catalogStr, table); } else { StringBuffer queryBuf = new StringBuffer( "SHOW TABLE STATUS "); queryBuf.append(" FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); queryBuf.append(" LIKE '"); queryBuf.append(table); queryBuf.append("'"); @@ -3297,8 +3642,8 @@ .hasMoreTokens()) { String keys = commentTokens .nextToken(); - getImportKeyResults(catalogStr - .toString(), table, + getImportKeyResults(catalogStr, + table, keys, rows); } } @@ -3348,8 +3693,8 @@ * @throws SQLException * if a database access error occurs */ - private void getImportKeyResults(String catalog, String importingTable, - String keysComment, List tuples) throws SQLException { + protected void getImportKeyResults(String catalog, String importingTable, + String keysComment, List tuples) throws SQLException { getResultsImpl(catalog, importingTable, keysComment, tuples, null, false); } @@ -3421,41 +3766,25 @@ * Sub_part */ - Field[] fields = new Field[13]; - fields[0] = new Field("", "TABLE_CAT", Types.CHAR, 255); - fields[1] = new Field("", "TABLE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "TABLE_NAME", Types.CHAR, 255); - fields[3] = new Field("", "NON_UNIQUE", Types.CHAR, 4); - fields[4] = new Field("", "INDEX_QUALIFIER", Types.CHAR, 1); - fields[5] = new Field("", "INDEX_NAME", Types.CHAR, 32); - fields[6] = new Field("", "TYPE", Types.CHAR, 32); - fields[7] = new Field("", "ORDINAL_POSITION", Types.SMALLINT, 5); - fields[8] = new Field("", "COLUMN_NAME", Types.CHAR, 32); - fields[9] = new Field("", "ASC_OR_DESC", Types.CHAR, 1); - fields[10] = new Field("", "CARDINALITY", Types.INTEGER, 10); - fields[11] = new Field("", "PAGES", Types.INTEGER, 10); - fields[12] = new Field("", "FILTER_CONDITION", Types.CHAR, 32); + Field[] fields = createIndexInfoFields(); - final ArrayList rows = new ArrayList(); + final SortedMap sortedRows = new TreeMap(); + final ArrayList rows = new ArrayList(); final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { ResultSet results = null; try { StringBuffer queryBuf = new StringBuffer( "SHOW INDEX FROM "); - queryBuf.append(quotedId); - queryBuf.append(table); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(table, conn.getPedantic())); queryBuf.append(" FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); try { results = stmt.executeQuery(queryBuf.toString()); @@ -3475,9 +3804,8 @@ while (results != null && results.next()) { byte[][] row = new byte[14][]; - row[0] = ((catalogStr.toString() == null) ? new byte[0] - : s2b(catalogStr.toString())); - ; + row[0] = ((catalogStr == null) ? new byte[0] + : s2b(catalogStr)); row[1] = null; row[2] = results.getBytes("Table"); @@ -3488,23 +3816,35 @@ : s2b("false")); row[4] = new byte[0]; row[5] = results.getBytes("Key_name"); - row[6] = Integer.toString( - java.sql.DatabaseMetaData.tableIndexOther) + short indexType = java.sql.DatabaseMetaData.tableIndexOther; + row[6] = Integer.toString(indexType) .getBytes(); row[7] = results.getBytes("Seq_in_index"); row[8] = results.getBytes("Column_name"); row[9] = results.getBytes("Collation"); - row[10] = results.getBytes("Cardinality"); + + // Cardinality can be much larger than Integer's range, + // so we clamp it to conform to the API + long cardinality = results.getLong("Cardinality"); + + if (cardinality > Integer.MAX_VALUE) { + cardinality = Integer.MAX_VALUE; + } + + row[10] = s2b(String.valueOf(cardinality)); row[11] = s2b("0"); row[12] = null; + IndexMetaDataKey indexInfoKey = new IndexMetaDataKey(!indexIsUnique, indexType, + results.getString("Key_name").toLowerCase(), results.getShort("Seq_in_index")); + if (unique) { if (indexIsUnique) { - rows.add(row); + sortedRows.put(indexInfoKey, new ByteArrayRow(row, getExceptionInterceptor())); } } else { // All rows match - rows.add(row); + sortedRows.put(indexInfoKey, new ByteArrayRow(row, getExceptionInterceptor())); } } } finally { @@ -3520,6 +3860,11 @@ } } }.doForAll(); + + Iterator sortedRowsIterator = sortedRows.values().iterator(); + while (sortedRowsIterator.hasNext()) { + rows.add(sortedRowsIterator.next()); + } java.sql.ResultSet indexInfo = buildResultSet(fields, rows); @@ -3531,11 +3876,29 @@ } } + protected Field[] createIndexInfoFields() { + Field[] fields = new Field[13]; + fields[0] = new Field("", "TABLE_CAT", Types.CHAR, 255); + fields[1] = new Field("", "TABLE_SCHEM", Types.CHAR, 0); + fields[2] = new Field("", "TABLE_NAME", Types.CHAR, 255); + fields[3] = new Field("", "NON_UNIQUE", Types.BOOLEAN, 4); + fields[4] = new Field("", "INDEX_QUALIFIER", Types.CHAR, 1); + fields[5] = new Field("", "INDEX_NAME", Types.CHAR, 32); + fields[6] = new Field("", "TYPE", Types.SMALLINT, 32); + fields[7] = new Field("", "ORDINAL_POSITION", Types.SMALLINT, 5); + fields[8] = new Field("", "COLUMN_NAME", Types.CHAR, 32); + fields[9] = new Field("", "ASC_OR_DESC", Types.CHAR, 1); + fields[10] = new Field("", "CARDINALITY", Types.INTEGER, 20); + fields[11] = new Field("", "PAGES", Types.INTEGER, 10); + fields[12] = new Field("", "FILTER_CONDITION", Types.CHAR, 32); + return fields; + } + /** * @see DatabaseMetaData#getJDBCMajorVersion() */ public int getJDBCMajorVersion() throws SQLException { - return 3; + return 4; } /** @@ -3815,34 +4178,29 @@ if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - final ArrayList rows = new ArrayList(); + final ArrayList rows = new ArrayList(); final Statement stmt = this.conn.getMetadataSafeStatement(); try { - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { ResultSet rs = null; try { StringBuffer queryBuf = new StringBuffer( "SHOW KEYS FROM "); - queryBuf.append(quotedId); - queryBuf.append(table); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(table, conn.getPedantic())); queryBuf.append(" FROM "); - queryBuf.append(quotedId); - queryBuf.append(catalogStr.toString()); - queryBuf.append(quotedId); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); rs = stmt.executeQuery(queryBuf.toString()); - ArrayList tuples = new ArrayList(); - TreeMap sortMap = new TreeMap(); + TreeMap sortMap = new TreeMap(); while (rs.next()) { String keyType = rs.getString("Key_name"); @@ -3851,8 +4209,8 @@ if (keyType.equalsIgnoreCase("PRIMARY") || keyType.equalsIgnoreCase("PRI")) { byte[][] tuple = new byte[6][]; - tuple[0] = ((catalogStr.toString() == null) ? new byte[0] - : s2b(catalogStr.toString())); + tuple[0] = ((catalogStr == null) ? new byte[0] + : s2b(catalogStr)); tuple[1] = null; tuple[2] = s2b(table); @@ -3867,10 +4225,10 @@ } // Now pull out in column name sorted order - Iterator sortedIterator = sortMap.values().iterator(); + Iterator sortedIterator = sortMap.values().iterator(); while (sortedIterator.hasNext()) { - rows.add(sortedIterator.next()); + rows.add(new ByteArrayRow(sortedIterator.next(), getExceptionInterceptor())); } } finally { @@ -3908,7 +4266,7 @@ * in column number order. *

*

- * Each row in the ResultSet is a parameter desription or column description + * Each row in the ResultSet is a parameter description or column description * with the following fields: *

    *
  1. PROCEDURE_CAT String => procedure catalog (may be null) @@ -3941,12 +4299,23 @@ * *
  2. *
  3. REMARKS String => comment describing parameter/column
  4. + *
  5. COLUMN_DEF String => default value for the column (may be null)
  6. + *
  7. SQL_DATA_TYPE int => reserved for future use
  8. + *
  9. SQL_DATETIME_SUB int => reserved for future use
  10. + *
  11. CHAR_OCTET_LENGTH int => the maximum length of binary and character based columns. For any other datatype the returned value is a NULL
  12. + *
  13. ORDINAL_POSITION int => the ordinal position, starting from 1. A value of 0 is returned if this row describes the procedure's return value.
  14. + *
  15. IS_NULLABLE String => ISO rules are used to determine the nullability for a column. + *
      + *
    • YES --- if the parameter can include NULLs
    • + *
    • NO --- if the parameter cannot include NULLs
    • + *
    • empty string --- if the nullability for the parameter is unknown
    • + *
    + *
  16. + *
  17. SPECIFIC_NAME String => the name which uniquely identifies this procedure within its schema.
  18. *
*

*

- * Note: Some databases may not return the column descriptions for a - * procedure. Additional columns beyond REMARKS can be defined by the - * database. + * Note: Some databases may not return the column descriptions for a procedure. *

* * @param catalog @@ -3966,73 +4335,179 @@ public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { + Field[] fields = createProcedureColumnsFields(); + + return getProcedureOrFunctionColumns( + fields, catalog, schemaPattern, + procedureNamePattern, columnNamePattern, + true, true); + } - Field[] fields = new Field[13]; + protected Field[] createProcedureColumnsFields() { + Field[] fields = new Field[20]; - fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0); - fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0); - fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 0); - fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 0); - fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 0); - fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 0); - fields[7] = new Field("", "PRECISION", Types.INTEGER, 0); - fields[8] = new Field("", "LENGTH", Types.INTEGER, 0); - fields[9] = new Field("", "SCALE", Types.SMALLINT, 0); - fields[10] = new Field("", "RADIX", Types.SMALLINT, 0); - fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 0); - fields[12] = new Field("", "REMARKS", Types.CHAR, 0); + fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 512); + fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 512); + fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 512); + fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 512); + fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 64); + fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 6); + fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 64); + fields[7] = new Field("", "PRECISION", Types.INTEGER, 12); + fields[8] = new Field("", "LENGTH", Types.INTEGER, 12); + fields[9] = new Field("", "SCALE", Types.SMALLINT, 12); + fields[10] = new Field("", "RADIX", Types.SMALLINT, 6); + fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 6); + fields[12] = new Field("", "REMARKS", Types.CHAR, 512); + fields[13] = new Field("", "COLUMN_DEF", Types.CHAR, 512); + fields[14] = new Field("", "SQL_DATA_TYPE", Types.INTEGER, 12); + fields[15] = new Field("", "SQL_DATETIME_SUB", Types.INTEGER, 12); + fields[16] = new Field("", "CHAR_OCTET_LENGTH", Types.INTEGER, 12); + fields[17] = new Field("", "ORDINAL_POSITION", Types.INTEGER, 12); + fields[18] = new Field("", "IS_NULLABLE", Types.CHAR, 512); + fields[19] = new Field("", "SPECIFIC_NAME", Types.CHAR, 512); + return fields; + } + + protected java.sql.ResultSet getProcedureOrFunctionColumns( + Field[] fields, String catalog, String schemaPattern, + String procedureOrFunctionNamePattern, + String columnNamePattern, boolean returnProcedures, + boolean returnFunctions) throws SQLException { - List proceduresToExtractList = new ArrayList(); - + List> procsOrFuncsToExtractList = new ArrayList>(); + //Main container to be passed to getProceduresAndOrFunctions + ResultSet procsAndOrFuncsRs = null; + if (supportsStoredProcedures()) { - if ((procedureNamePattern.indexOf("%") == -1) - && (procedureNamePattern.indexOf("?") == -1)) { - proceduresToExtractList.add(procedureNamePattern); - } else { + try { + //getProceduresAndOrFunctions does NOT expect procedureOrFunctionNamePattern + //in form of DB_NAME.SP_NAME thus we need to remove it + String tmpProcedureOrFunctionNamePattern = null; + //Check if NOT a pattern first, then "sanitize" + if ((procedureOrFunctionNamePattern != null) && (!procedureOrFunctionNamePattern.equals("%"))) { + tmpProcedureOrFunctionNamePattern = StringUtils.sanitizeProcOrFuncName(procedureOrFunctionNamePattern); + } - ResultSet procedureNameRs = null; + //Sanity check, if NamePattern is still NULL, we have a wildcard and not the name + if (tmpProcedureOrFunctionNamePattern == null) { + tmpProcedureOrFunctionNamePattern = procedureOrFunctionNamePattern; + } else { + //So we have a name to check meaning more actual processing + //Keep the Catalog parsed, maybe we'll need it at some point + //in the future... + String tmpCatalog = catalog; + List parseList = StringUtils.splitDBdotName(tmpProcedureOrFunctionNamePattern, tmpCatalog, + this.quotedId, this.conn.isNoBackslashEscapesSet()); + + //There *should* be 2 rows, if any. + if (parseList.size() == 2) { + tmpCatalog = parseList.get(0); + tmpProcedureOrFunctionNamePattern = parseList.get(1); + } else { + //keep values as they are + } + } + + procsAndOrFuncsRs = getProceduresAndOrFunctions( + createFieldMetadataForGetProcedures(), + catalog, schemaPattern, + tmpProcedureOrFunctionNamePattern, returnProcedures, + returnFunctions); - try { + // Demand: PARAM_CAT for SP. + // Goal: proceduresToExtractList has to have db.sp entries. + + // Due to https://intranet.mysql.com/secure/paste/displaypaste.php?codeid=10704 + // introducing new variables, ignoring ANSI mode + + String tmpstrPNameRs = null; + String tmpstrCatNameRs = null; - procedureNameRs = getProcedures(catalog, schemaPattern, - procedureNamePattern); - - while (procedureNameRs.next()) { - proceduresToExtractList.add(procedureNameRs - .getString(3)); + boolean hasResults = false; + while (procsAndOrFuncsRs.next()) { + tmpstrCatNameRs = procsAndOrFuncsRs.getString(1); + tmpstrPNameRs = procsAndOrFuncsRs.getString(3); + + if (!((tmpstrCatNameRs.startsWith(this.quotedId) && tmpstrCatNameRs.endsWith(this.quotedId)) || + (tmpstrCatNameRs.startsWith("\"") && tmpstrCatNameRs.endsWith("\"")))) { + tmpstrCatNameRs = this.quotedId + tmpstrCatNameRs + this.quotedId; } + if (!((tmpstrPNameRs.startsWith(this.quotedId) && tmpstrPNameRs.endsWith(this.quotedId)) || + (tmpstrPNameRs.startsWith("\"") && tmpstrPNameRs.endsWith("\"")))) { + tmpstrPNameRs = this.quotedId + tmpstrPNameRs + this.quotedId; + } - // Required to be sorted in name-order by JDBC spec, - // in 'normal' case getProcedures takes care of this for us, - // but if system tables are inaccessible, we need to sort... - // so just do this to be safe... - Collections.sort(proceduresToExtractList); - } finally { - SQLException rethrowSqlEx = null; + procsOrFuncsToExtractList.add(new ComparableWrapper( + tmpstrCatNameRs + "." + tmpstrPNameRs, + procsAndOrFuncsRs.getShort(8) == procedureNoResult ? PROCEDURE + : FUNCTION)); + hasResults = true; + } - if (procedureNameRs != null) { - try { - procedureNameRs.close(); - } catch (SQLException sqlEx) { - rethrowSqlEx = sqlEx; - } - } + // FIX for Bug#56305, allowing the code to proceed with empty fields causing NPE later + if (!hasResults) { +// throw SQLError.createSQLException( +// "User does not have access to metadata required to determine " + +// "stored procedure parameter types. If rights can not be granted, configure connection with \"noAccessToProcedureBodies=true\" " + +// "to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.", +// SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } else { + Collections.sort(procsOrFuncsToExtractList); + } - if (rethrowSqlEx != null) { - throw rethrowSqlEx; + // Required to be sorted in name-order by JDBC spec, + // in 'normal' case getProcedures takes care of this for us, + // but if system tables are inaccessible, we need to sort... + // so just do this to be safe... + //Collections.sort(proceduresToExtractList); + } finally { + SQLException rethrowSqlEx = null; + + if (procsAndOrFuncsRs != null) { + try { + procsAndOrFuncsRs.close(); + } catch (SQLException sqlEx) { + rethrowSqlEx = sqlEx; } } + + if (rethrowSqlEx != null) { + throw rethrowSqlEx; + } } } - ArrayList resultRows = new ArrayList(); + ArrayList resultRows = new ArrayList(); + int idx = 0; + String procNameToCall = ""; + + for (ComparableWrapper procOrFunc : procsOrFuncsToExtractList) { + String procName = procOrFunc.getKey(); + ProcedureType procType = procOrFunc.getValue(); - for (Iterator iter = proceduresToExtractList.iterator(); iter.hasNext();) { - String procName = (String) iter.next(); - - getCallStmtParameterTypes(catalog, procName, columnNamePattern, - resultRows); + //Continuing from above (database_name.sp_name) + if (!" ".equals(this.quotedId)) { + idx = StringUtils.indexOfIgnoreCaseRespectQuotes(0, + procName, ".", this.quotedId.charAt(0), !this.conn + .isNoBackslashEscapesSet()); + } else { + idx = procName.indexOf("."); + } + + if (idx > 0) { + catalog = procName.substring(0,idx); + if (quotedId != " " && catalog.startsWith(quotedId) && catalog.endsWith(quotedId)) { + catalog = procName.substring(1, catalog.length() - 1); + } + procNameToCall = procName; // Leave as CAT.PROC, needed later + } else { + //No catalog. Not sure how to handle right now... + procNameToCall = procName; + } + getCallStmtParameterTypes(catalog, procNameToCall, procType, columnNamePattern, + resultRows, + fields.length == 17 /* for getFunctionColumns */); } return buildResultSet(fields, resultRows); @@ -4081,52 +4556,84 @@ public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { - return getProceduresAndOrFunctions(catalog, schemaPattern, + Field[] fields = createFieldMetadataForGetProcedures(); + + return getProceduresAndOrFunctions(fields, catalog, schemaPattern, procedureNamePattern, true, true); } - protected java.sql.ResultSet getProceduresAndOrFunctions(String catalog, - String schemaPattern, String procedureNamePattern, - final boolean returnProcedures, final boolean returnFunctions) - throws SQLException { + protected Field[] createFieldMetadataForGetProcedures() { + Field[] fields = new Field[9]; + fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 255); + fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 255); + fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 255); + fields[3] = new Field("", "reserved1", Types.CHAR, 0); + fields[4] = new Field("", "reserved2", Types.CHAR, 0); + fields[5] = new Field("", "reserved3", Types.CHAR, 0); + fields[6] = new Field("", "REMARKS", Types.CHAR, 255); + fields[7] = new Field("", "PROCEDURE_TYPE", Types.SMALLINT, 6); + fields[8] = new Field("", "SPECIFIC_NAME", Types.CHAR, 255); + + return fields; + } + + /** + * + * @param fields + * @param catalog + * @param schemaPattern + * @param procedureNamePattern + * @param returnProcedures + * @param returnFunctions + * @return + * @throws SQLException + */ + protected java.sql.ResultSet getProceduresAndOrFunctions( + final Field[] fields, + String catalog, + String schemaPattern, + String procedureNamePattern, + final boolean returnProcedures, + final boolean returnFunctions) throws SQLException { if ((procedureNamePattern == null) || (procedureNamePattern.length() == 0)) { if (this.conn.getNullNamePatternMatchesAll()) { procedureNamePattern = "%"; } else { throw SQLError.createSQLException( "Procedure name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } - Field[] fields = new Field[8]; - fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0); - fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0); - fields[3] = new Field("", "reserved1", Types.CHAR, 0); - fields[4] = new Field("", "reserved2", Types.CHAR, 0); - fields[5] = new Field("", "reserved3", Types.CHAR, 0); - fields[6] = new Field("", "REMARKS", Types.CHAR, 0); - fields[7] = new Field("", "PROCEDURE_TYPE", Types.SMALLINT, 0); + final ArrayList procedureRows = new ArrayList(); - final ArrayList procedureRows = new ArrayList(); - if (supportsStoredProcedures()) { final String procNamePattern = procedureNamePattern; - final Map procedureRowsOrderedByName = new TreeMap(); + final List> procedureRowsToSort = new ArrayList>(); - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { - String db = catalogStr.toString(); + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { + String db = catalogStr; boolean fromSelect = false; ResultSet proceduresRs = null; boolean needsClientFiltering = true; - PreparedStatement proceduresStmt = conn - .clientPrepareStatement("SELECT name, type FROM mysql.proc WHERE name like ? and db <=> ? ORDER BY name"); + StringBuffer selectFromMySQLProcSQL = new StringBuffer(); + + selectFromMySQLProcSQL.append("SELECT name, type, comment FROM mysql.proc WHERE "); + if (returnProcedures && !returnFunctions) { + selectFromMySQLProcSQL.append("type = 'PROCEDURE' and "); + } else if (!returnProcedures && returnFunctions) { + selectFromMySQLProcSQL.append("type = 'FUNCTION' and "); + } + selectFromMySQLProcSQL.append("name like ? and db <=> ? ORDER BY name, type"); + + java.sql.PreparedStatement proceduresStmt = conn.clientPrepareStatement(selectFromMySQLProcSQL + .toString()); + try { // // Try using system tables first, as this is a little @@ -4136,6 +4643,9 @@ boolean hasTypeColumn = false; if (db != null) { + if(conn.lowerCaseTableNames()){ + db = db.toLowerCase(); + } proceduresStmt.setString(2, db); } else { proceduresStmt.setNull(2, Types.VARCHAR); @@ -4171,7 +4681,7 @@ nameIndex = 1; } - proceduresStmt = conn + proceduresStmt = conn .clientPrepareStatement("SHOW PROCEDURE STATUS LIKE ?"); if (proceduresStmt.getMaxRows() != 0) { @@ -4185,8 +4695,8 @@ if (returnProcedures) { convertToJdbcProcedureList(fromSelect, db, - proceduresRs, needsClientFiltering, db, - procedureRowsOrderedByName, nameIndex); + proceduresRs, needsClientFiltering, db, + procedureRowsToSort, nameIndex); } if (!hasTypeColumn) { @@ -4206,20 +4716,19 @@ proceduresRs = proceduresStmt.executeQuery(); - if (returnFunctions) { - convertToJdbcFunctionList(db, proceduresRs, - needsClientFiltering, db, - procedureRowsOrderedByName, nameIndex); - } } + //Should be here, not in IF block! + if (returnFunctions) { + convertToJdbcFunctionList(db, proceduresRs, + needsClientFiltering, db, + procedureRowsToSort, nameIndex, + fields); + } // Now, sort them - - Iterator proceduresIter = procedureRowsOrderedByName - .values().iterator(); - - while (proceduresIter.hasNext()) { - procedureRows.add(proceduresIter.next()); + Collections.sort(procedureRowsToSort); + for (ComparableWrapper procRow : procedureRowsToSort) { + procedureRows.add(procRow.getValue()); } } finally { SQLException rethrowSqlEx = null; @@ -4251,6 +4760,7 @@ return buildResultSet(fields, procedureRows); } + /** * What's the database vendor's preferred term for "procedure"? * @@ -4270,7 +4780,7 @@ } private void getResultsImpl(String catalog, String table, - String keysComment, List tuples, String fkTableName, + String keysComment, List tuples, String fkTableName, boolean isExport) throws SQLException { LocalAndReferencedColumns parsedInfo = parseTableStatusIntoLocalAndReferencedColumns(keysComment); @@ -4281,24 +4791,21 @@ if (parsedInfo.localColumnsList.size() != parsedInfo.referencedColumnsList .size()) { - throw SQLError - .createSQLException( - "Error parsing foreign keys definition," - + "number of local and referenced columns is not the same.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException( + "Error parsing foreign keys definition," + + "number of local and referenced columns is not the same.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - Iterator localColumnNames = parsedInfo.localColumnsList.iterator(); - Iterator referColumnNames = parsedInfo.referencedColumnsList.iterator(); + Iterator localColumnNames = parsedInfo.localColumnsList.iterator(); + Iterator referColumnNames = parsedInfo.referencedColumnsList.iterator(); int keySeqIndex = 1; while (localColumnNames.hasNext()) { byte[][] tuple = new byte[14][]; - String lColumnName = removeQuotedId(localColumnNames.next() - .toString()); - String rColumnName = removeQuotedId(referColumnNames.next() - .toString()); + String lColumnName = StringUtils.unQuoteIdentifier(localColumnNames.next(), this.conn.useAnsiQuotedIdentifiers()); + String rColumnName = StringUtils.unQuoteIdentifier(referColumnNames.next(), this.conn.useAnsiQuotedIdentifiers()); tuple[FKTABLE_CAT] = ((catalog == null) ? new byte[0] : s2b(catalog)); tuple[FKTABLE_SCHEM] = null; @@ -4319,7 +4826,7 @@ tuple[PK_NAME] = null; // not available from show table status tuple[DEFERRABILITY] = s2b(Integer .toString(java.sql.DatabaseMetaData.importedKeyNotDeferrable)); - tuples.add(tuple); + tuples.add(new ByteArrayRow(tuple, getExceptionInterceptor())); } } @@ -4340,10 +4847,10 @@ */ public java.sql.ResultSet getSchemas() throws SQLException { Field[] fields = new Field[2]; - fields[0] = new Field("", "TABLE_SCHEM", java.sql.Types.CHAR, 0); - fields[1] = new Field("", "TABLE_CATALOG", java.sql.Types.CHAR, 0); + fields[0] = new Field("", "TABLE_SCHEM", java.sql.Types.CHAR, 0); + fields[1] = new Field("", "TABLE_CATALOG", java.sql.Types.CHAR, 0); - ArrayList tuples = new ArrayList(); + ArrayList tuples = new ArrayList(); java.sql.ResultSet results = buildResultSet(fields, tuples); return results; @@ -4379,15 +4886,36 @@ } /** - * Get a comma separated list of all a database's SQL keywords that are NOT - * also SQL92 keywords. + * Get a comma separated list of all a database's SQL keywords that are NOT also SQL92/SQL2003 keywords. * * @return the list * @throws SQLException * DOCUMENT ME! */ public String getSQLKeywords() throws SQLException { - return mysqlKeywordsThatArentSQL92; + if (mysqlKeywords != null) { + return mysqlKeywords; + } + + synchronized (DatabaseMetaData.class) { + // double check, maybe it's already set + if (mysqlKeywords != null) { + return mysqlKeywords; + } + + Set mysqlKeywordSet = new TreeSet(); + StringBuffer mysqlKeywordsBuffer = new StringBuffer(); + + Collections.addAll(mysqlKeywordSet, MYSQL_KEYWORDS); + mysqlKeywordSet.removeAll(Arrays.asList(Util.isJdbc4() ? SQL2003_KEYWORDS : SQL92_KEYWORDS)); + + for (String keyword : mysqlKeywordSet) { + mysqlKeywordsBuffer.append(",").append(keyword); + } + + mysqlKeywords = mysqlKeywordsBuffer.substring(1); + return mysqlKeywords; + } } /** @@ -4433,7 +4961,7 @@ fields[2] = new Field("", "TABLE_NAME", Types.CHAR, 32); fields[3] = new Field("", "SUPERTABLE_NAME", Types.CHAR, 32); - return buildResultSet(fields, new ArrayList()); + return buildResultSet(fields, new ArrayList()); } /** @@ -4442,14 +4970,14 @@ public java.sql.ResultSet getSuperTypes(String arg0, String arg1, String arg2) throws SQLException { Field[] fields = new Field[6]; - fields[0] = new Field("", "TABLE_CAT", Types.CHAR, 32); - fields[1] = new Field("", "TABLE_SCHEM", Types.CHAR, 32); + fields[0] = new Field("", "TYPE_CAT", Types.CHAR, 32); + fields[1] = new Field("", "TYPE_SCHEM", Types.CHAR, 32); fields[2] = new Field("", "TYPE_NAME", Types.CHAR, 32); fields[3] = new Field("", "SUPERTYPE_CAT", Types.CHAR, 32); fields[4] = new Field("", "SUPERTYPE_SCHEM", Types.CHAR, 32); fields[5] = new Field("", "SUPERTYPE_NAME", Types.CHAR, 32); - return buildResultSet(fields, new ArrayList()); + return buildResultSet(fields, new ArrayList()); } /** @@ -4463,7 +4991,7 @@ return "DATABASE,USER,SYSTEM_USER,SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION"; } - private String getTableNameWithCase(String table) { + protected String getTableNameWithCase(String table) { String tableNameWithCase = (this.conn.lowerCaseTableNames() ? table .toLowerCase() : table); @@ -4513,7 +5041,7 @@ } else { throw SQLError.createSQLException( "Table name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @@ -4541,7 +5069,7 @@ grantQuery.append("'"); ResultSet results = null; - ArrayList grantRows = new ArrayList(); + ArrayList grantRows = new ArrayList(); Statement stmt = null; try { @@ -4600,7 +5128,7 @@ tuple[4] = s2b(fullUser.toString()); tuple[5] = s2b(privilege); tuple[6] = null; - grantRows.add(tuple); + grantRows.add(new ByteArrayRow(tuple, getExceptionInterceptor())); } } finally { if (columnResults != null) { @@ -4684,77 +5212,88 @@ } else { throw SQLError.createSQLException( "Table name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } - Field[] fields = new Field[5]; - fields[0] = new Field("", "TABLE_CAT", java.sql.Types.VARCHAR, 255); - fields[1] = new Field("", "TABLE_SCHEM", java.sql.Types.VARCHAR, 0); - fields[2] = new Field("", "TABLE_NAME", java.sql.Types.VARCHAR, 255); - fields[3] = new Field("", "TABLE_TYPE", java.sql.Types.VARCHAR, 5); - fields[4] = new Field("", "REMARKS", java.sql.Types.VARCHAR, 0); + final SortedMap sortedRows = new TreeMap(); + final ArrayList tuples = new ArrayList(); - final ArrayList tuples = new ArrayList(); - final Statement stmt = this.conn.getMetadataSafeStatement(); - final String tableNamePat = tableNamePattern; + final String tableNamePat; + String tmpCat = ""; + + if ((catalog == null) || (catalog.length() == 0)) { + if (this.conn.getNullCatalogMeansCurrent()) { + tmpCat = this.database; + } + } else { + tmpCat = catalog; + } + + List parseList = StringUtils.splitDBdotName(tableNamePattern, tmpCat, + quotedId , conn.isNoBackslashEscapesSet()); + //There *should* be 2 rows, if any. + if (parseList.size() == 2) { + tableNamePat = parseList.get(1); + } else { + tableNamePat = tableNamePattern; + } try { + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { + boolean operatingOnSystemDB = "information_schema".equalsIgnoreCase(catalogStr) + || "mysql".equalsIgnoreCase(catalogStr) + || "performance_schema".equalsIgnoreCase(catalogStr); - new IterateBlock(getCatalogIterator(catalog)) { - void forEach(Object catalogStr) throws SQLException { ResultSet results = null; try { - if (!conn.versionMeetsMinimum(5, 0, 2)) { - try { - results = stmt.executeQuery("SHOW TABLES FROM " - + quotedId + catalogStr.toString() - + quotedId + " LIKE '" + tableNamePat - + "'"); - } catch (SQLException sqlEx) { - if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE - .equals(sqlEx.getSQLState())) { - throw sqlEx; - } - - return; + try { + results = stmt.executeQuery((!conn.versionMeetsMinimum(5, 0, 2) ? "SHOW TABLES FROM " + : "SHOW FULL TABLES FROM ") + + StringUtils.quoteIdentifier(catalogStr, conn.getPedantic()) + + " LIKE '" + + tableNamePat + "'"); + } catch (SQLException sqlEx) { + if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE.equals(sqlEx.getSQLState())) { + throw sqlEx; } - } else { - try { - results = stmt - .executeQuery("SHOW FULL TABLES FROM " - + quotedId - + catalogStr.toString() - + quotedId + " LIKE '" - + tableNamePat + "'"); - } catch (SQLException sqlEx) { - if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE - .equals(sqlEx.getSQLState())) { - throw sqlEx; - } - return; - } + return; } boolean shouldReportTables = false; boolean shouldReportViews = false; - + boolean shouldReportSystemTables = false; + boolean shouldReportSystemViews = false; + boolean shouldReportLocalTemporaries = false; + if (types == null || types.length == 0) { shouldReportTables = true; shouldReportViews = true; + shouldReportSystemTables = true; + shouldReportSystemViews = true; + shouldReportLocalTemporaries = true; } else { for (int i = 0; i < types.length; i++) { - if ("TABLE".equalsIgnoreCase(types[i])) { + if (TableType.TABLE.equalsTo(types[i])) { shouldReportTables = true; - } - if ("VIEW".equalsIgnoreCase(types[i])) { + } else if (TableType.VIEW.equalsTo(types[i])) { shouldReportViews = true; + + } else if (TableType.SYSTEM_TABLE.equalsTo(types[i])) { + shouldReportSystemTables = true; + + } else if (TableType.SYSTEM_VIEW.equalsTo(types[i])) { + shouldReportSystemViews = true; + + } else if (TableType.LOCAL_TEMPORARY.equalsTo(types[i])) { + shouldReportLocalTemporaries = true; } } } @@ -4790,100 +5329,108 @@ } } - TreeMap tablesOrderedByName = null; - TreeMap viewsOrderedByName = null; - while (results.next()) { - byte[][] row = new byte[5][]; - row[0] = (catalogStr.toString() == null) ? null - : s2b(catalogStr.toString()); + byte[][] row = new byte[10][]; + row[0] = (catalogStr == null) ? null + : s2b(catalogStr); row[1] = null; row[2] = results.getBytes(1); row[4] = new byte[0]; + row[5] = null; + row[6] = null; + row[7] = null; + row[8] = null; + row[9] = null; if (hasTableTypes) { String tableType = results .getString(typeColumnIndex); - if (("table".equalsIgnoreCase(tableType) || "base table" - .equalsIgnoreCase(tableType)) - && shouldReportTables) { - row[3] = TABLE_AS_BYTES; + switch (TableType.getTableTypeCompliantWith(tableType)) { + case TABLE: + boolean reportTable = false; + TableMetaDataKey tablesKey = null; - if (tablesOrderedByName == null) { - tablesOrderedByName = new TreeMap(); - } + if (operatingOnSystemDB && shouldReportSystemTables) { + row[3] = TableType.SYSTEM_TABLE.asBytes(); + tablesKey = new TableMetaDataKey(TableType.SYSTEM_TABLE.getName(), + catalogStr, null, results.getString(1)); + reportTable = true; - tablesOrderedByName.put(results - .getString(1), row); - } else if ("view".equalsIgnoreCase(tableType) - && shouldReportViews) { - row[3] = VIEW_AS_BYTES; + } else if (!operatingOnSystemDB && shouldReportTables) { + row[3] = TableType.TABLE.asBytes(); + tablesKey = new TableMetaDataKey(TableType.TABLE.getName(), catalogStr, + null, results.getString(1)); + reportTable = true; + } - if (viewsOrderedByName == null) { - viewsOrderedByName = new TreeMap(); - } + if (reportTable) { + sortedRows.put(tablesKey, new ByteArrayRow(row, getExceptionInterceptor())); + } + break; - viewsOrderedByName.put( - results.getString(1), row); - } else if (!hasTableTypes) { - // punt? - row[3] = TABLE_AS_BYTES; + case VIEW: + if (shouldReportViews) { + row[3] = TableType.VIEW.asBytes(); + sortedRows.put(new TableMetaDataKey(TableType.VIEW.getName(), + catalogStr, null, results.getString(1)), new ByteArrayRow(row, + getExceptionInterceptor())); + } + break; - if (tablesOrderedByName == null) { - tablesOrderedByName = new TreeMap(); - } + case SYSTEM_TABLE: + if (shouldReportSystemTables) { + row[3] = TableType.SYSTEM_TABLE.asBytes(); + sortedRows.put(new TableMetaDataKey(TableType.SYSTEM_TABLE.getName(), + catalogStr, null, results.getString(1)), new ByteArrayRow(row, + getExceptionInterceptor())); + } + break; - tablesOrderedByName.put(results - .getString(1), row); + case SYSTEM_VIEW: + if (shouldReportSystemViews) { + row[3] = TableType.SYSTEM_VIEW.asBytes(); + sortedRows.put(new TableMetaDataKey(TableType.SYSTEM_VIEW.getName(), + catalogStr, null, results.getString(1)), new ByteArrayRow(row, + getExceptionInterceptor())); + } + break; + + case LOCAL_TEMPORARY: + if (shouldReportLocalTemporaries) { + row[3] = TableType.LOCAL_TEMPORARY.asBytes(); + sortedRows.put(new TableMetaDataKey(TableType.LOCAL_TEMPORARY.getName(), + catalogStr, null, results.getString(1)), new ByteArrayRow(row, + getExceptionInterceptor())); + } + break; + + default: + row[3] = TableType.TABLE.asBytes(); + sortedRows.put(new TableMetaDataKey(TableType.TABLE.getName(), catalogStr, + null, results.getString(1)), new ByteArrayRow(row, + getExceptionInterceptor())); + break; } } else { if (shouldReportTables) { // Pre-MySQL-5.0.1, tables only - row[3] = TABLE_AS_BYTES; - - if (tablesOrderedByName == null) { - tablesOrderedByName = new TreeMap(); - } - - tablesOrderedByName.put(results - .getString(1), row); + row[3] = TableType.TABLE.asBytes(); + sortedRows.put(new TableMetaDataKey(TableType.TABLE.getName(), catalogStr, null, + results.getString(1)), new ByteArrayRow(row, getExceptionInterceptor())); } } } - // They are ordered by TABLE_TYPE, - // * TABLE_SCHEM and TABLE_NAME. - - if (tablesOrderedByName != null) { - Iterator tablesIter = tablesOrderedByName.values() - .iterator(); - - while (tablesIter.hasNext()) { - tuples.add(tablesIter.next()); - } - } - - if (viewsOrderedByName != null) { - Iterator viewsIter = viewsOrderedByName.values() - .iterator(); - - while (viewsIter.hasNext()) { - tuples.add(viewsIter.next()); - } - } - } finally { if (results != null) { try { results.close(); } catch (Exception ex) { - ; } results = null; } - } } }.doForAll(); @@ -4893,10 +5440,26 @@ } } - java.sql.ResultSet tables = buildResultSet(fields, tuples); + tuples.addAll(sortedRows.values()); + java.sql.ResultSet tables = buildResultSet(createTablesFields(), tuples); return tables; } + + protected Field[] createTablesFields() { + Field[] fields = new Field[10]; + fields[0] = new Field("", "TABLE_CAT", java.sql.Types.VARCHAR, 255); + fields[1] = new Field("", "TABLE_SCHEM", java.sql.Types.VARCHAR, 0); + fields[2] = new Field("", "TABLE_NAME", java.sql.Types.VARCHAR, 255); + fields[3] = new Field("", "TABLE_TYPE", java.sql.Types.VARCHAR, 5); + fields[4] = new Field("", "REMARKS", java.sql.Types.VARCHAR, 0); + fields[5] = new Field("", "TYPE_CAT", java.sql.Types.VARCHAR, 0); + fields[6] = new Field("", "TYPE_SCHEM", java.sql.Types.VARCHAR, 0); + fields[7] = new Field("", "TYPE_NAME", java.sql.Types.VARCHAR, 0); + fields[8] = new Field("", "SELF_REFERENCING_COL_NAME", java.sql.Types.VARCHAR, 0); + fields[9] = new Field("", "REF_GENERATION", java.sql.Types.VARCHAR, 0); + return fields; + } /** * Get the table types available in this database. The results are ordered @@ -4916,24 +5479,21 @@ * DOCUMENT ME! */ public java.sql.ResultSet getTableTypes() throws SQLException { - ArrayList tuples = new ArrayList(); - Field[] fields = new Field[1]; - fields[0] = new Field("", "TABLE_TYPE", Types.VARCHAR, 5); + ArrayList tuples = new ArrayList(); + Field[] fields = new Field[] { new Field("", "TABLE_TYPE", Types.VARCHAR, 256) }; - byte[][] tableTypeRow = new byte[1][]; - tableTypeRow[0] = TABLE_AS_BYTES; - tuples.add(tableTypeRow); + boolean minVersion5_0_1 = this.conn.versionMeetsMinimum(5, 0, 1); - if (this.conn.versionMeetsMinimum(5, 0, 1)) { - byte[][] viewTypeRow = new byte[1][]; - viewTypeRow[0] = VIEW_AS_BYTES; - tuples.add(viewTypeRow); + tuples.add(new ByteArrayRow(new byte[][] { TableType.LOCAL_TEMPORARY.asBytes() }, getExceptionInterceptor())); + tuples.add(new ByteArrayRow(new byte[][] { TableType.SYSTEM_TABLE.asBytes() }, getExceptionInterceptor())); + if (minVersion5_0_1) { + tuples.add(new ByteArrayRow(new byte[][] { TableType.SYSTEM_VIEW.asBytes() }, getExceptionInterceptor())); } + tuples.add(new ByteArrayRow(new byte[][] { TableType.TABLE.asBytes() }, getExceptionInterceptor())); + if (minVersion5_0_1) { + tuples.add(new ByteArrayRow(new byte[][] { TableType.VIEW.asBytes() }, getExceptionInterceptor())); + } - byte[][] tempTypeRow = new byte[1][]; - tempTypeRow[0] = s2b("LOCAL TEMPORARY"); - tuples.add(tempTypeRow); - return buildResultSet(fields, tuples); } @@ -5056,17 +5616,17 @@ public java.sql.ResultSet getTypeInfo() throws SQLException { Field[] fields = new Field[18]; fields[0] = new Field("", "TYPE_NAME", Types.CHAR, 32); - fields[1] = new Field("", "DATA_TYPE", Types.SMALLINT, 5); + fields[1] = new Field("", "DATA_TYPE", Types.INTEGER, 5); fields[2] = new Field("", "PRECISION", Types.INTEGER, 10); fields[3] = new Field("", "LITERAL_PREFIX", Types.CHAR, 4); fields[4] = new Field("", "LITERAL_SUFFIX", Types.CHAR, 4); fields[5] = new Field("", "CREATE_PARAMS", Types.CHAR, 32); fields[6] = new Field("", "NULLABLE", Types.SMALLINT, 5); - fields[7] = new Field("", "CASE_SENSITIVE", Types.CHAR, 3); + fields[7] = new Field("", "CASE_SENSITIVE", Types.BOOLEAN, 3); fields[8] = new Field("", "SEARCHABLE", Types.SMALLINT, 3); - fields[9] = new Field("", "UNSIGNED_ATTRIBUTE", Types.CHAR, 3); - fields[10] = new Field("", "FIXED_PREC_SCALE", Types.CHAR, 3); - fields[11] = new Field("", "AUTO_INCREMENT", Types.CHAR, 3); + fields[9] = new Field("", "UNSIGNED_ATTRIBUTE", Types.BOOLEAN, 3); + fields[10] = new Field("", "FIXED_PREC_SCALE", Types.BOOLEAN, 3); + fields[11] = new Field("", "AUTO_INCREMENT", Types.BOOLEAN, 3); fields[12] = new Field("", "LOCAL_TYPE_NAME", Types.CHAR, 32); fields[13] = new Field("", "MINIMUM_SCALE", Types.SMALLINT, 5); fields[14] = new Field("", "MAXIMUM_SCALE", Types.SMALLINT, 5); @@ -5075,7 +5635,7 @@ fields[17] = new Field("", "NUM_PREC_RADIX", Types.INTEGER, 10); byte[][] rowVal = null; - ArrayList tuples = new ArrayList(); + ArrayList tuples = new ArrayList(); /* * The following are ordered by java.sql.Types, and then by how closely @@ -5111,7 +5671,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: BOOL (silently converted to TINYINT(1)) JDBC Type: BIT @@ -5143,7 +5703,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: TINYINT JDBC Type: TINYINT @@ -5175,7 +5735,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); rowVal = new byte[18][]; rowVal[0] = s2b("TINYINT UNSIGNED"); @@ -5204,7 +5764,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: BIGINT JDBC Type: BIGINT @@ -5236,7 +5796,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); rowVal = new byte[18][]; rowVal[0] = s2b("BIGINT UNSIGNED"); @@ -5265,7 +5825,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: LONG VARBINARY JDBC Type: LONGVARBINARY @@ -5297,7 +5857,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: MEDIUMBLOB JDBC Type: LONGVARBINARY @@ -5329,7 +5889,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: LONGBLOB JDBC Type: LONGVARBINARY @@ -5363,7 +5923,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: BLOB JDBC Type: LONGVARBINARY @@ -5395,7 +5955,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: TINYBLOB JDBC Type: LONGVARBINARY @@ -5427,7 +5987,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: VARBINARY (sliently converted to VARCHAR(M) BINARY) JDBC @@ -5460,7 +6020,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: BINARY (silently converted to CHAR(M) BINARY) JDBC Type: @@ -5493,7 +6053,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: LONG VARCHAR JDBC Type: LONGVARCHAR @@ -5525,7 +6085,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: MEDIUMTEXT JDBC Type: LONGVARCHAR @@ -5557,7 +6117,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: LONGTEXT JDBC Type: LONGVARCHAR @@ -5591,7 +6151,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: TEXT JDBC Type: LONGVARCHAR @@ -5623,7 +6183,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: TINYTEXT JDBC Type: LONGVARCHAR @@ -5655,7 +6215,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: CHAR JDBC Type: CHAR @@ -5687,7 +6247,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); // The maximum number of digits for DECIMAL or NUMERIC is 65 (64 from MySQL 5.0.3 to 5.0.5). @@ -5732,7 +6292,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: DECIMAL JDBC Type: DECIMAL @@ -5764,7 +6324,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: INTEGER JDBC Type: INTEGER @@ -5796,7 +6356,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); rowVal = new byte[18][]; rowVal[0] = s2b("INTEGER UNSIGNED"); @@ -5825,7 +6385,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: INT JDBC Type: INTEGER @@ -5857,7 +6417,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); rowVal = new byte[18][]; rowVal[0] = s2b("INT UNSIGNED"); @@ -5886,7 +6446,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: MEDIUMINT JDBC Type: INTEGER @@ -5918,7 +6478,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); rowVal = new byte[18][]; rowVal[0] = s2b("MEDIUMINT UNSIGNED"); @@ -5947,7 +6507,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: SMALLINT JDBC Type: SMALLINT @@ -5979,7 +6539,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); rowVal = new byte[18][]; rowVal[0] = s2b("SMALLINT UNSIGNED"); @@ -6008,7 +6568,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: FLOAT JDBC Type: REAL (this is the SINGLE PERCISION @@ -6041,7 +6601,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: DOUBLE JDBC Type: DOUBLE @@ -6073,7 +6633,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: DOUBLE PRECISION JDBC Type: DOUBLE @@ -6105,7 +6665,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: REAL (does not map to Types.REAL) JDBC Type: DOUBLE @@ -6137,7 +6697,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: VARCHAR JDBC Type: VARCHAR @@ -6169,7 +6729,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: ENUM JDBC Type: VARCHAR @@ -6201,7 +6761,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: SET JDBC Type: VARCHAR @@ -6233,7 +6793,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: DATE JDBC Type: DATE @@ -6265,7 +6825,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: TIME JDBC Type: TIME @@ -6297,7 +6857,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: DATETIME JDBC Type: TIMESTAMP @@ -6329,7 +6889,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); /* * MySQL Type: TIMESTAMP JDBC Type: TIMESTAMP @@ -6361,7 +6921,7 @@ rowVal[15] = s2b("0"); // SQL Data Type (not used) rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used) rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10) - tuples.add(rowVal); + tuples.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); return buildResultSet(fields, tuples); } @@ -6409,15 +6969,16 @@ */ public java.sql.ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { - Field[] fields = new Field[6]; + Field[] fields = new Field[7]; fields[0] = new Field("", "TYPE_CAT", Types.VARCHAR, 32); fields[1] = new Field("", "TYPE_SCHEM", Types.VARCHAR, 32); fields[2] = new Field("", "TYPE_NAME", Types.VARCHAR, 32); fields[3] = new Field("", "CLASS_NAME", Types.VARCHAR, 32); - fields[4] = new Field("", "DATA_TYPE", Types.VARCHAR, 32); + fields[4] = new Field("", "DATA_TYPE", Types.INTEGER, 10); fields[5] = new Field("", "REMARKS", Types.VARCHAR, 32); + fields[6] = new Field("", "BASE_TYPE", Types.SMALLINT, 10); - ArrayList tuples = new ArrayList(); + ArrayList tuples = new ArrayList(); return buildResultSet(fields, tuples); } @@ -6514,20 +7075,158 @@ * DOCUMENT ME! */ public java.sql.ResultSet getVersionColumns(String catalog, String schema, - String table) throws SQLException { + final String table) throws SQLException { + + if (table == null) { + throw SQLError.createSQLException("Table not specified.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + Field[] fields = new Field[8]; fields[0] = new Field("", "SCOPE", Types.SMALLINT, 5); fields[1] = new Field("", "COLUMN_NAME", Types.CHAR, 32); - fields[2] = new Field("", "DATA_TYPE", Types.SMALLINT, 5); + fields[2] = new Field("", "DATA_TYPE", Types.INTEGER, 5); fields[3] = new Field("", "TYPE_NAME", Types.CHAR, 16); - fields[4] = new Field("", "COLUMN_SIZE", Types.CHAR, 16); - fields[5] = new Field("", "BUFFER_LENGTH", Types.CHAR, 16); - fields[6] = new Field("", "DECIMAL_DIGITS", Types.CHAR, 16); + fields[4] = new Field("", "COLUMN_SIZE", Types.INTEGER, 16); + fields[5] = new Field("", "BUFFER_LENGTH", Types.INTEGER, 16); + fields[6] = new Field("", "DECIMAL_DIGITS", Types.SMALLINT, 16); fields[7] = new Field("", "PSEUDO_COLUMN", Types.SMALLINT, 5); - return buildResultSet(fields, new ArrayList()); + final ArrayList rows = new ArrayList(); - // do TIMESTAMP columns count? + final Statement stmt = this.conn.getMetadataSafeStatement(); + + try { + + new IterateBlock(getCatalogIterator(catalog)) { + void forEach(String catalogStr) throws SQLException { + + ResultSet results = null; + boolean with_where = conn.versionMeetsMinimum(5, 0, 0); + + try { + StringBuffer whereBuf = new StringBuffer(" Extra LIKE '%on update CURRENT_TIMESTAMP%'"); + List rsFields = new ArrayList(); + + // for versions prior to 5.1.23 we can get "on update CURRENT_TIMESTAMP" + // only from SHOW CREATE TABLE + if (!conn.versionMeetsMinimum(5, 1, 23)) { + + whereBuf = new StringBuffer(); + boolean firstTime = true; + + String query = new StringBuffer("SHOW CREATE TABLE ") + .append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())).append(".") + .append(StringUtils.quoteIdentifier(table, conn.getPedantic())).toString(); + + results = stmt.executeQuery(query); + while (results.next()) { + String createTableString = results.getString(2); + StringTokenizer lineTokenizer = new StringTokenizer(createTableString, "\n"); + + while (lineTokenizer.hasMoreTokens()) { + String line = lineTokenizer.nextToken().trim(); + if (StringUtils.indexOfIgnoreCase(line, "on update CURRENT_TIMESTAMP") > -1) { + boolean usingBackTicks = true; + int beginPos = line.indexOf(quotedId); + + if (beginPos == -1) { + beginPos = line.indexOf("\""); + usingBackTicks = false; + } + + if (beginPos != -1) { + int endPos = -1; + + if (usingBackTicks) { + endPos = line.indexOf(quotedId, beginPos + 1); + } else { + endPos = line.indexOf("\"", beginPos + 1); + } + + if (endPos != -1) { + if (with_where) { + if (!firstTime) { + whereBuf.append(" or"); + } else { + firstTime = false; + } + whereBuf.append(" Field='"); + whereBuf.append(line.substring(beginPos + 1, endPos)); + whereBuf.append("'"); + } else { + rsFields.add(line.substring(beginPos + 1, endPos)); + } + } + } + } + } + } + } + + if (whereBuf.length() > 0 || rsFields.size() > 0) { + StringBuffer queryBuf = new StringBuffer("SHOW "); + queryBuf.append("COLUMNS FROM "); + queryBuf.append(StringUtils.quoteIdentifier(table, conn.getPedantic())); + queryBuf.append(" FROM "); + queryBuf.append(StringUtils.quoteIdentifier(catalogStr, conn.getPedantic())); + if (with_where) { + queryBuf.append(" WHERE"); + queryBuf.append(whereBuf.toString()); + } + + results = stmt.executeQuery(queryBuf.toString()); + + while (results.next()) { + if (with_where || rsFields.contains(results.getString("Field"))) { + TypeDescriptor typeDesc = new TypeDescriptor(results.getString("Type"), results.getString("Null")); + byte[][] rowVal = new byte[8][]; + // SCOPE is not used + rowVal[0] = null; + // COLUMN_NAME + rowVal[1] = results.getBytes("Field"); + // DATA_TYPE + rowVal[2] = Short.toString(typeDesc.dataType).getBytes(); + // TYPE_NAME + rowVal[3] = s2b(typeDesc.typeName); + // COLUMN_SIZE + rowVal[4] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize.toString()); + // BUFFER_LENGTH + rowVal[5] = s2b(Integer.toString(typeDesc.bufferLength)); + // DECIMAL_DIGITS + rowVal[6] = typeDesc.decimalDigits == null ? null : s2b(typeDesc.decimalDigits.toString()); + // PSEUDO_COLUMN + rowVal[7] = Integer.toString(java.sql.DatabaseMetaData.versionColumnNotPseudo).getBytes(); + + rows.add(new ByteArrayRow(rowVal, getExceptionInterceptor())); + } + } + } + } catch (SQLException sqlEx) { + if (!SQLError.SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND.equals(sqlEx.getSQLState())) { + throw sqlEx; + } + } finally { + if (results != null) { + try { + results.close(); + } catch (Exception ex) { + ; + } + + results = null; + } + } + + } + }.doForAll(); + } finally { + if (stmt != null) { + stmt.close(); + } + } + + return buildResultSet(fields, rows); } /** @@ -6709,7 +7408,7 @@ return false; } - private LocalAndReferencedColumns parseTableStatusIntoLocalAndReferencedColumns( + protected LocalAndReferencedColumns parseTableStatusIntoLocalAndReferencedColumns( String keysComment) throws SQLException { // keys will equal something like this: // (parent_service_id child_service_id) REFER @@ -6737,14 +7436,14 @@ true); if (indexOfOpenParenLocalColumns == -1) { - throw SQLError.createSQLException( - "Error parsing foreign keys definition," - + " couldn't find start of local columns list.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException("Error parsing foreign keys definition," + + " couldn't find start of local columns list.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - String constraintName = removeQuotedId(keysComment.substring(0, - indexOfOpenParenLocalColumns).trim()); + String constraintName = StringUtils.unQuoteIdentifier( + keysComment.substring(0, indexOfOpenParenLocalColumns).trim(), + this.conn.useAnsiQuotedIdentifiers()); keysComment = keysComment.substring(indexOfOpenParenLocalColumns, keysComment.length()); @@ -6755,10 +7454,9 @@ quoteChar, true); if (indexOfCloseParenLocalColumns == -1) { - throw SQLError.createSQLException( - "Error parsing foreign keys definition," - + " couldn't find end of local columns list.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException("Error parsing foreign keys definition," + + " couldn't find end of local columns list.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } String localColumnNamesString = keysCommentTrimmed.substring(1, @@ -6768,23 +7466,19 @@ keysCommentTrimmed, "REFER ", this.quotedId.charAt(0), true); if (indexOfRefer == -1) { - throw SQLError - .createSQLException( - "Error parsing foreign keys definition," - + " couldn't find start of referenced tables list.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException("Error parsing foreign keys definition," + + " couldn't find start of referenced tables list.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } int indexOfOpenParenReferCol = StringUtils .indexOfIgnoreCaseRespectQuotes(indexOfRefer, keysCommentTrimmed, "(", quoteChar, false); if (indexOfOpenParenReferCol == -1) { - throw SQLError - .createSQLException( - "Error parsing foreign keys definition," - + " couldn't find start of referenced columns list.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException("Error parsing foreign keys definition," + + " couldn't find start of referenced columns list.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } String referCatalogTableString = keysCommentTrimmed.substring( @@ -6794,66 +7488,40 @@ referCatalogTableString, "/", this.quotedId.charAt(0), false); if (indexOfSlash == -1) { - throw SQLError.createSQLException( - "Error parsing foreign keys definition," - + " couldn't find name of referenced catalog.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException("Error parsing foreign keys definition," + + " couldn't find name of referenced catalog.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - String referCatalog = removeQuotedId(referCatalogTableString.substring( - 0, indexOfSlash)); - String referTable = removeQuotedId(referCatalogTableString.substring( - indexOfSlash + 1).trim()); + String referCatalog = StringUtils.unQuoteIdentifier( + referCatalogTableString.substring(0, indexOfSlash), + this.conn.useAnsiQuotedIdentifiers()); + String referTable = StringUtils.unQuoteIdentifier( + referCatalogTableString.substring(indexOfSlash + 1).trim(), + this.conn.useAnsiQuotedIdentifiers()); int indexOfCloseParenRefer = StringUtils .indexOfIgnoreCaseRespectQuotes(indexOfOpenParenReferCol, keysCommentTrimmed, ")", quoteChar, true); if (indexOfCloseParenRefer == -1) { - throw SQLError.createSQLException( - "Error parsing foreign keys definition," - + " couldn't find end of referenced columns list.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError.createSQLException("Error parsing foreign keys definition," + + " couldn't find end of referenced columns list.", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } String referColumnNamesString = keysCommentTrimmed.substring( indexOfOpenParenReferCol + 1, indexOfCloseParenRefer); - List referColumnsList = StringUtils.split(referColumnNamesString, + List referColumnsList = StringUtils.split(referColumnNamesString, columnsDelimitter, this.quotedId, this.quotedId, false); - List localColumnsList = StringUtils.split(localColumnNamesString, + List localColumnsList = StringUtils.split(localColumnNamesString, columnsDelimitter, this.quotedId, this.quotedId, false); return new LocalAndReferencedColumns(localColumnsList, referColumnsList, constraintName, referCatalog, referTable); } - private String removeQuotedId(String s) { - if (s == null) { - return null; - } - - if (this.quotedId.equals("")) { - return s; - } - - s = s.trim(); - - int frontOffset = 0; - int backOffset = s.length(); - int quoteLength = this.quotedId.length(); - - if (s.startsWith(this.quotedId)) { - frontOffset = quoteLength; - } - - if (s.endsWith(this.quotedId)) { - backOffset -= quoteLength; - } - - return s.substring(frontOffset, backOffset); - } - /** * Converts the given string to bytes, using the connection's character * encoding, or if not available, the JVM default encoding. @@ -6862,8 +7530,14 @@ * DOCUMENT ME! * @return DOCUMENT ME! */ - private byte[] s2b(String s) throws SQLException { - return StringUtils.s2b(s, this.conn); + protected byte[] s2b(String s) throws SQLException { + if (s == null) { + return null; + } + + return StringUtils.getBytes(s, this.conn.getCharacterSetMetadata(), + this.conn.getServerCharacterEncoding(), this.conn + .parserKnowsUnicode(), this.conn, getExceptionInterceptor()); } /** @@ -6875,7 +7549,7 @@ * DOCUMENT ME! */ public boolean storesLowerCaseIdentifiers() throws SQLException { - return this.conn.lowerCaseTableNames(); + return this.conn.storesLowerCaseTableName(); } /** @@ -6887,7 +7561,7 @@ * DOCUMENT ME! */ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - return this.conn.lowerCaseTableNames(); + return this.conn.storesLowerCaseTableName(); } /** @@ -6899,9 +7573,8 @@ * DOCUMENT ME! */ public boolean storesMixedCaseIdentifiers() throws SQLException { - return !this.conn.lowerCaseTableNames(); + return !this.conn.storesLowerCaseTableName(); } - /** * Does the database store mixed case quoted SQL identifiers in mixed case? * A JDBC compliant driver will always return false. @@ -6911,7 +7584,7 @@ * DOCUMENT ME! */ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - return !this.conn.lowerCaseTableNames(); + return !this.conn.storesLowerCaseTableName(); } /** @@ -7144,16 +7817,16 @@ return false; } - /* - * We don't handle the BIT type yet. - */ + /* + * We don't handle the BIT type yet. + */ case java.sql.Types.BIT: return false; - /* - * The numeric types. Basically they can convert among themselves, - * and with char/binary types. - */ + /* + * The numeric types. Basically they can convert among themselves, and + * with char/binary types. + */ case java.sql.Types.DECIMAL: case java.sql.Types.NUMERIC: case java.sql.Types.REAL: @@ -7186,14 +7859,14 @@ return false; } - /* MySQL doesn't support a NULL type. */ + /* MySQL doesn't support a NULL type. */ case java.sql.Types.NULL: return false; - /* - * With this driver, this will always be a serialized object, so the - * char/binary types will work. - */ + /* + * With this driver, this will always be a serialized object, so the + * char/binary types will work. + */ case java.sql.Types.OTHER: switch (toType) { @@ -7209,7 +7882,7 @@ return false; } - /* Dates can be converted to char/binary types. */ + /* Dates can be converted to char/binary types. */ case java.sql.Types.DATE: switch (toType) { @@ -7225,7 +7898,7 @@ return false; } - /* Time can be converted to char/binary types */ + /* Time can be converted to char/binary types */ case java.sql.Types.TIME: switch (toType) { @@ -7241,10 +7914,10 @@ return false; } - /* - * Timestamp can be converted to char/binary types and date/time - * types (with loss of precision). - */ + /* + * Timestamp can be converted to char/binary types and date/time types + * (with loss of precision). + */ case java.sql.Types.TIMESTAMP: switch (toType) { @@ -7262,7 +7935,7 @@ return false; } - /* We shouldn't get here! */ + /* We shouldn't get here! */ default: return false; // not sure } @@ -7415,8 +8088,8 @@ public boolean supportsIntegrityEnhancementFacility() throws SQLException { if (!this.conn.getOverrideSupportsIntegrityEnhancementFacility()) { return false; - } - + } + return true; } @@ -7494,7 +8167,7 @@ * DOCUMENT ME! */ public boolean supportsMultipleResultSets() throws SQLException { - return false; + return this.conn.versionMeetsMinimum(4, 1, 0); } /** @@ -7640,26 +8313,26 @@ if ((concurrency == ResultSet.CONCUR_READ_ONLY) || (concurrency == ResultSet.CONCUR_UPDATABLE)) { return true; - } else { - throw SQLError.createSQLException( - "Illegal arguments to supportsResultSetConcurrency()", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } + throw SQLError.createSQLException( + "Illegal arguments to supportsResultSetConcurrency()", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + case ResultSet.TYPE_FORWARD_ONLY: if ((concurrency == ResultSet.CONCUR_READ_ONLY) || (concurrency == ResultSet.CONCUR_UPDATABLE)) { return true; - } else { - throw SQLError.createSQLException( - "Illegal arguments to supportsResultSetConcurrency()", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } + throw SQLError.createSQLException( + "Illegal arguments to supportsResultSetConcurrency()", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + case ResultSet.TYPE_SCROLL_SENSITIVE: return false; default: throw SQLError.createSQLException( "Illegal arguments to supportsResultSetConcurrency()", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @@ -7937,4 +8610,233 @@ public boolean usesLocalFiles() throws SQLException { return false; } + + // + // JDBC-4.0 functions that aren't reliant on Java6 + // + + /** + * Retrieves a list of the client info properties that the driver supports. The result set contains the following + * columns + *

+ *

    + *
  1. NAME String=> The name of the client info property
    + *
  2. MAX_LEN int=> The maximum length of the value for the property
    + *
  3. DEFAULT_VALUE String=> The default value of the property
    + *
  4. DESCRIPTION String=> A description of the property. This will typically contain information as to + * where this property is stored in the database. + *
+ *

+ * The ResultSet is sorted by the NAME column + *

+ * + * @return A ResultSet object; each row is a supported client info property + *

+ * @exception SQLException + * if a database access error occurs + *

+ * @since 1.6 + */ + public ResultSet getClientInfoProperties() throws SQLException { + // We don't have any built-ins, we actually support whatever + // the client wants to provide, however we don't have a way + // to express this with the interface given + Field[] fields = new Field[4]; + fields[0] = new Field("", "NAME", Types.VARCHAR, 255); + fields[1] = new Field("", "MAX_LEN", Types.INTEGER, 10); + fields[2] = new Field("", "DEFAULT_VALUE", Types.VARCHAR, 255); + fields[3] = new Field("", "DESCRIPTION", Types.VARCHAR, 255); + + return buildResultSet(fields, new ArrayList(), this.conn); + } + + /** + * Retrieves a description of the given catalog's system or user + * function parameters and return type. + * + * @see java.sql.DatabaseMetaData#getFunctionColumns(String, String, String, String) + * @since 1.6 + */ + public ResultSet getFunctionColumns(String catalog, + String schemaPattern, + String functionNamePattern, + String columnNamePattern) throws SQLException { + Field[] fields = createFunctionColumnsFields(); + + return getProcedureOrFunctionColumns( + fields, catalog, schemaPattern, + functionNamePattern, columnNamePattern, + false, true); + } + + protected Field[] createFunctionColumnsFields() { + Field[] fields = { + new Field("", "FUNCTION_CAT", Types.VARCHAR, 512), + new Field("", "FUNCTION_SCHEM", Types.VARCHAR, 512), + new Field("", "FUNCTION_NAME", Types.VARCHAR, 512), + new Field("", "COLUMN_NAME", Types.VARCHAR, 512), + new Field("", "COLUMN_TYPE", Types.VARCHAR, 64), + new Field("", "DATA_TYPE", Types.SMALLINT, 6), + new Field("", "TYPE_NAME", Types.VARCHAR, 64), + new Field("", "PRECISION", Types.INTEGER, 12), + new Field("", "LENGTH", Types.INTEGER, 12), + new Field("", "SCALE", Types.SMALLINT, 12), + new Field("", "RADIX", Types.SMALLINT, 6), + new Field("", "NULLABLE", Types.SMALLINT, 6), + new Field("", "REMARKS", Types.VARCHAR, 512), + new Field("", "CHAR_OCTET_LENGTH", Types.INTEGER, 32), + new Field("", "ORDINAL_POSITION", Types.INTEGER, 32), + new Field("", "IS_NULLABLE", Types.VARCHAR, 12), + new Field("", "SPECIFIC_NAME", Types.VARCHAR, 64)}; + return fields; + } + + /** + * Retrieves a description of the system and user functions available + * in the given catalog. + *

+ * Only system and user function descriptions matching the schema and + * function name criteria are returned. They are ordered by + * FUNCTION_CAT, FUNCTION_SCHEM, + * FUNCTION_NAME and + * SPECIFIC_ NAME. + * + *

Each function description has the the following columns: + *

    + *
  1. FUNCTION_CAT String => function catalog (may be null) + *
  2. FUNCTION_SCHEM String => function schema (may be null) + *
  3. FUNCTION_NAME String => function name. This is the name + * used to invoke the function + *
  4. REMARKS String => explanatory comment on the function + *
  5. FUNCTION_TYPE short => kind of function: + *
      + *
    • functionResultUnknown - Cannot determine if a return value + * or table will be returned + *
    • functionNoTable- Does not return a table + *
    • functionReturnsTable - Returns a table + *
    + *
  6. SPECIFIC_NAME String => the name which uniquely identifies + * this function within its schema. This is a user specified, or DBMS + * generated, name that may be different then the FUNCTION_NAME + * for example with overload functions + *
+ *

+ * A user may not have permission to execute any of the functions that are + * returned by getFunctions + * + * @param catalog a catalog name; must match the catalog name as it + * is stored in the database; "" retrieves those without a catalog; + * null means that the catalog name should not be used to narrow + * the search + * @param schemaPattern a schema name pattern; must match the schema name + * as it is stored in the database; "" retrieves those without a schema; + * null means that the schema name should not be used to narrow + * the search + * @param functionNamePattern a function name pattern; must match the + * function name as it is stored in the database + * @return ResultSet - each row is a function description + * @exception SQLException if a database access error occurs + * @see #getSearchStringEscape + * @since 1.6 + */ + public java.sql.ResultSet getFunctions(String catalog, String schemaPattern, + String functionNamePattern) throws SQLException { + Field[] fields = new Field[6]; + + fields[0] = new Field("", "FUNCTION_CAT", Types.CHAR, 255); + fields[1] = new Field("", "FUNCTION_SCHEM", Types.CHAR, 255); + fields[2] = new Field("", "FUNCTION_NAME", Types.CHAR, 255); + fields[3] = new Field("", "REMARKS", Types.CHAR, 255); + fields[4] = new Field("", "FUNCTION_TYPE", Types.SMALLINT, 6); + fields[5] = new Field("", "SPECIFIC_NAME", Types.CHAR, 255); + + return getProceduresAndOrFunctions( + fields, + catalog, + schemaPattern, + functionNamePattern, + false, + true); + } + + public boolean providesQueryObjectGenerator() throws SQLException { + return false; + } + + /** + * + * @param catalog + * @param schemaPattern + * @return + * @throws SQLException + */ + public ResultSet getSchemas(String catalog, + String schemaPattern) throws SQLException { + Field[] fields = { + new Field("", "TABLE_SCHEM", Types.VARCHAR, 255), + new Field("", "TABLE_CATALOG", Types.VARCHAR, 255) + }; + + return buildResultSet(fields, new ArrayList()); + } + + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return true; + } + + /** + * Get a prepared statement to query information_schema tables. + * + * @return PreparedStatement + * @throws SQLException + */ + protected java.sql.PreparedStatement prepareMetaDataSafeStatement(String sql) + throws SQLException { + // Can't use server-side here as we coerce a lot of types to match + // the spec. + java.sql.PreparedStatement pStmt = this.conn.clientPrepareStatement(sql); + + if (pStmt.getMaxRows() != 0) { + pStmt.setMaxRows(0); + } + + ((com.mysql.jdbc.Statement) pStmt).setHoldResultsOpenOverClose(true); + + return pStmt; + } + + /** + * JDBC-4.1 + * + * @param catalog + * @param schemaPattern + * @param tableNamePattern + * @param columnNamePattern + * @return + * @throws SQLException + */ + public java.sql.ResultSet getPseudoColumns(String catalog, + String schemaPattern, String tableNamePattern, + String columnNamePattern) throws SQLException { + Field[] fields = { new Field("", "TABLE_CAT", Types.VARCHAR, 512), + new Field("", "TABLE_SCHEM", Types.VARCHAR, 512), + new Field("", "TABLE_NAME", Types.VARCHAR, 512), + new Field("", "COLUMN_NAME", Types.VARCHAR, 512), + new Field("", "DATA_TYPE", Types.INTEGER, 12), + new Field("", "COLUMN_SIZE", Types.INTEGER, 12), + new Field("", "DECIMAL_DIGITS", Types.INTEGER, 12), + new Field("", "NUM_PREC_RADIX", Types.INTEGER, 12), + new Field("", "COLUMN_USAGE", Types.VARCHAR, 512), + new Field("", "REMARKS", Types.VARCHAR, 512), + new Field("", "CHAR_OCTET_LENGTH", Types.INTEGER, 12), + new Field("", "IS_NULLABLE", Types.VARCHAR, 512) }; + + return buildResultSet(fields, new ArrayList()); + } + + // JDBC-4.1 + public boolean generatedKeyAlwaysReturned() + throws SQLException { + return true; + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/DatabaseMetaDataUsingInfoSchema.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/DatabaseMetaDataUsingInfoSchema.java (.../DatabaseMetaDataUsingInfoSchema.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/DatabaseMetaDataUsingInfoSchema.java (.../DatabaseMetaDataUsingInfoSchema.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,32 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ + package com.mysql.jdbc; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; +import java.util.List; /** * DatabaseMetaData implementation that uses INFORMATION_SCHEMA available in @@ -35,15 +37,41 @@ */ public class DatabaseMetaDataUsingInfoSchema extends DatabaseMetaData { - public DatabaseMetaDataUsingInfoSchema(Connection connToSet, - String databaseToSet) { + protected enum JDBC4FunctionConstant { + // COLUMN_TYPE values + FUNCTION_COLUMN_UNKNOWN, FUNCTION_COLUMN_IN, FUNCTION_COLUMN_INOUT, FUNCTION_COLUMN_OUT, + FUNCTION_COLUMN_RETURN, FUNCTION_COLUMN_RESULT, + // NULLABLE values + FUNCTION_NO_NULLS, FUNCTION_NULLABLE, FUNCTION_NULLABLE_UNKNOWN; + } + + private boolean hasReferentialConstraintsView; + private final boolean hasParametersView; + + protected DatabaseMetaDataUsingInfoSchema(MySQLConnection connToSet, + String databaseToSet) throws SQLException { super(connToSet, databaseToSet); + + this.hasReferentialConstraintsView = + this.conn.versionMeetsMinimum(5, 1, 10); + + ResultSet rs = null; + + try { + rs = super.getTables("INFORMATION_SCHEMA", null, "PARAMETERS", new String[0]); + + this.hasParametersView = rs.next(); + } finally { + if (rs != null) { + rs.close(); + } + } } - private ResultSet executeMetadataQuery(PreparedStatement pStmt) + protected ResultSet executeMetadataQuery(java.sql.PreparedStatement pStmt) throws SQLException { ResultSet rs = pStmt.executeQuery(); - ((com.mysql.jdbc.ResultSet) rs).setOwningStatement(null); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).setOwningStatement(null); return rs; } @@ -92,7 +120,7 @@ } else { throw SQLError.createSQLException( "Column name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @@ -109,7 +137,7 @@ + "TABLE_NAME =? AND COLUMN_NAME LIKE ? ORDER BY " + "COLUMN_NAME, PRIVILEGE_TYPE"; - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -124,7 +152,7 @@ pStmt.setString(3, columnNamePattern); ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(new Field[] { new Field("", "TABLE_CAT", Types.CHAR, 64), new Field("", "TABLE_SCHEM", Types.CHAR, 1), new Field("", "TABLE_NAME", Types.CHAR, 64), @@ -194,7 +222,7 @@ } else { throw SQLError.createSQLException( "Column name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @@ -212,15 +240,14 @@ sqlBuf.append(" AS DATA_TYPE, "); if (conn.getCapitalizeTypeNames()) { - sqlBuf.append("UPPER(CASE WHEN LOCATE('unsigned', COLUMN_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END) AS TYPE_NAME,"); + sqlBuf.append("UPPER(CASE WHEN LOCATE('unsigned', COLUMN_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 AND LOCATE('set', DATA_TYPE) <> 1 AND LOCATE('enum', DATA_TYPE) <> 1 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END) AS TYPE_NAME,"); } else { - sqlBuf.append("CASE WHEN LOCATE('unsigned', COLUMN_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END AS TYPE_NAME,"); + sqlBuf.append("CASE WHEN LOCATE('unsigned', COLUMN_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 AND LOCATE('set', DATA_TYPE) <> 1 AND LOCATE('enum', DATA_TYPE) <> 1 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END AS TYPE_NAME,"); } sqlBuf - .append("CASE WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION ELSE CASE WHEN CHARACTER_MAXIMUM_LENGTH > " - + Integer.MAX_VALUE + " THEN " + Integer.MAX_VALUE + - " ELSE CHARACTER_MAXIMUM_LENGTH END END AS COLUMN_SIZE, " + .append("CASE WHEN LCASE(DATA_TYPE)='date' THEN 10 WHEN LCASE(DATA_TYPE)='time' THEN 8 WHEN LCASE(DATA_TYPE)='datetime' THEN 19 WHEN LCASE(DATA_TYPE)='timestamp' THEN 19 WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION WHEN CHARACTER_MAXIMUM_LENGTH > " + + Integer.MAX_VALUE + " THEN " + Integer.MAX_VALUE + " ELSE CHARACTER_MAXIMUM_LENGTH END AS COLUMN_SIZE, " + MysqlIO.getMaxBuf() + " AS BUFFER_LENGTH," + "NUMERIC_SCALE AS DECIMAL_DIGITS," + "10 AS NUM_PREC_RADIX," @@ -237,13 +264,44 @@ + "NULL AS SCOPE_TABLE," + "NULL AS SOURCE_DATA_TYPE," + "IF (EXTRA LIKE '%auto_increment%','YES','NO') AS IS_AUTOINCREMENT " - + "FROM INFORMATION_SCHEMA.COLUMNS WHERE " - + "TABLE_SCHEMA LIKE ? AND " - + "TABLE_NAME LIKE ? AND COLUMN_NAME LIKE ? " - + "ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION"); + + "FROM INFORMATION_SCHEMA.COLUMNS WHERE "); - PreparedStatement pStmt = null; + final boolean operatingOnInformationSchema = "information_schema".equalsIgnoreCase(catalog); + + if (catalog != null) { + if ((operatingOnInformationSchema) || ((StringUtils.indexOfIgnoreCase(0, catalog, "%") == -1) + && (StringUtils.indexOfIgnoreCase(0, catalog, "_") == -1))) { + sqlBuf.append("TABLE_SCHEMA = ? AND "); + } else { + sqlBuf.append("TABLE_SCHEMA LIKE ? AND "); + } + + } else { + sqlBuf.append("TABLE_SCHEMA LIKE ? AND "); + } + if (tableName != null) { + if ((StringUtils.indexOfIgnoreCase(0, tableName, "%") == -1) + && (StringUtils.indexOfIgnoreCase(0, tableName, "_") == -1)) { + sqlBuf.append("TABLE_NAME = ? AND "); + } else { + sqlBuf.append("TABLE_NAME LIKE ? AND "); + } + + } else { + sqlBuf.append("TABLE_NAME LIKE ? AND "); + } + + if ((StringUtils.indexOfIgnoreCase(0, columnNamePattern, "%") == -1) + && (StringUtils.indexOfIgnoreCase(0, columnNamePattern, "_") == -1)) { + sqlBuf.append("COLUMN_NAME = ? "); + } else { + sqlBuf.append("COLUMN_NAME LIKE ? "); + } + sqlBuf.append("ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION"); + + java.sql.PreparedStatement pStmt = null; + try { pStmt = prepareMetaDataSafeStatement(sqlBuf.toString()); @@ -258,32 +316,7 @@ ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "TABLE_CAT", Types.CHAR, 255), - new Field("", "TABLE_SCHEM", Types.CHAR, 0), - new Field("", "TABLE_NAME", Types.CHAR, 255), - new Field("", "COLUMN_NAME", Types.CHAR, 32), - new Field("", "DATA_TYPE", Types.SMALLINT, 5), - new Field("", "TYPE_NAME", Types.CHAR, 16), - new Field("", "COLUMN_SIZE", Types.INTEGER, Integer - .toString(Integer.MAX_VALUE).length()), - new Field("", "BUFFER_LENGTH", Types.INTEGER, 10), - new Field("", "DECIMAL_DIGITS", Types.INTEGER, 10), - new Field("", "NUM_PREC_RADIX", Types.INTEGER, 10), - new Field("", "NULLABLE", Types.INTEGER, 10), - new Field("", "REMARKS", Types.CHAR, 0), - new Field("", "COLUMN_DEF", Types.CHAR, 0), - new Field("", "SQL_DATA_TYPE", Types.INTEGER, 10), - new Field("", "SQL_DATETIME_SUB", Types.INTEGER, 10), - new Field("", "CHAR_OCTET_LENGTH", Types.INTEGER, Integer - .toString(Integer.MAX_VALUE).length()), - new Field("", "ORDINAL_POSITION", Types.INTEGER, 10), - new Field("", "IS_NULLABLE", Types.CHAR, 3), - new Field("", "SCOPE_CATALOG", Types.CHAR, 255), - new Field("", "SCOPE_SCHEMA", Types.CHAR, 255), - new Field("", "SCOPE_TABLE", Types.CHAR, 255), - new Field("", "SOURCE_DATA_TYPE", Types.SMALLINT, 10), - new Field("", "IS_AUTOINCREMENT", Types.CHAR, 3) }); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createColumnsFields()); return rs; } finally { if (pStmt != null) { @@ -364,7 +397,7 @@ String foreignSchema, String foreignTable) throws SQLException { if (primaryTable == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } if (primaryCatalog == null) { @@ -379,22 +412,6 @@ } } - Field[] fields = new Field[14]; - fields[0] = new Field("", "PKTABLE_CAT", Types.CHAR, 255); - fields[1] = new Field("", "PKTABLE_SCHEM", Types.CHAR, 0); - fields[2] = new Field("", "PKTABLE_NAME", Types.CHAR, 255); - fields[3] = new Field("", "PKCOLUMN_NAME", Types.CHAR, 32); - fields[4] = new Field("", "FKTABLE_CAT", Types.CHAR, 255); - fields[5] = new Field("", "FKTABLE_SCHEM", Types.CHAR, 0); - fields[6] = new Field("", "FKTABLE_NAME", Types.CHAR, 255); - fields[7] = new Field("", "FKCOLUMN_NAME", Types.CHAR, 32); - fields[8] = new Field("", "KEY_SEQ", Types.SMALLINT, 2); - fields[9] = new Field("", "UPDATE_RULE", Types.SMALLINT, 2); - fields[10] = new Field("", "DELETE_RULE", Types.SMALLINT, 2); - fields[11] = new Field("", "FK_NAME", Types.CHAR, 0); - fields[12] = new Field("", "PK_NAME", Types.CHAR, 0); - fields[13] = new Field("", "DEFERRABILITY", Types.INTEGER, 2); - String sql = "SELECT " + "A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT," + "NULL AS PKTABLE_SCHEM," @@ -405,26 +422,31 @@ + "A.TABLE_NAME AS FKTABLE_NAME, " + "A.COLUMN_NAME AS FKCOLUMN_NAME, " + "A.ORDINAL_POSITION AS KEY_SEQ," - + importedKeyRestrict + + generateUpdateRuleClause() + " AS UPDATE_RULE," - + importedKeyRestrict + + generateDeleteRuleClause() + " AS DELETE_RULE," + "A.CONSTRAINT_NAME AS FK_NAME," - + "NULL AS PK_NAME," + + "(SELECT CONSTRAINT_NAME FROM" + + " INFORMATION_SCHEMA.TABLE_CONSTRAINTS" + + " WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA AND" + + " TABLE_NAME = A.REFERENCED_TABLE_NAME AND" + + " CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1)" + + " AS PK_NAME," + importedKeyNotDeferrable + " AS DEFERRABILITY " + "FROM " - + "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A," + + "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A JOIN " + "INFORMATION_SCHEMA.TABLE_CONSTRAINTS B " + + "USING (TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME) " + + generateOptionalRefContraintsJoin() + "WHERE " - + "A.TABLE_SCHEMA=B.TABLE_SCHEMA AND A.TABLE_NAME=B.TABLE_NAME " - + "AND " - + "A.CONSTRAINT_NAME=B.CONSTRAINT_NAME AND B.CONSTRAINT_TYPE IS NOT NULL " + + "B.CONSTRAINT_TYPE = 'FOREIGN KEY' " + "AND A.REFERENCED_TABLE_SCHEMA LIKE ? AND A.REFERENCED_TABLE_NAME=? " + "AND A.TABLE_SCHEMA LIKE ? AND A.TABLE_NAME=? " + "ORDER BY " + "A.TABLE_SCHEMA, A.TABLE_NAME, A.ORDINAL_POSITION"; - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -445,21 +467,7 @@ pStmt.setString(4, foreignTable); ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "PKTABLE_CAT", Types.CHAR, 255), - new Field("", "PKTABLE_SCHEM", Types.CHAR, 0), - new Field("", "PKTABLE_NAME", Types.CHAR, 255), - new Field("", "PKCOLUMN_NAME", Types.CHAR, 32), - new Field("", "FKTABLE_CAT", Types.CHAR, 255), - new Field("", "FKTABLE_SCHEM", Types.CHAR, 0), - new Field("", "FKTABLE_NAME", Types.CHAR, 255), - new Field("", "FKCOLUMN_NAME", Types.CHAR, 32), - new Field("", "KEY_SEQ", Types.SMALLINT, 2), - new Field("", "UPDATE_RULE", Types.SMALLINT, 2), - new Field("", "DELETE_RULE", Types.SMALLINT, 2), - new Field("", "FK_NAME", Types.CHAR, 0), - new Field("", "PK_NAME", Types.CHAR, 0), - new Field("", "DEFERRABILITY", Types.INTEGER, 2) }); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createFkMetadataFields()); return rs; } finally { @@ -534,14 +542,16 @@ if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } if (catalog == null) { if (this.conn.getNullCatalogMeansCurrent()) { catalog = this.database; } } + + //CASCADE, SET NULL, SET DEFAULT, RESTRICT, NO ACTION String sql = "SELECT " + "A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT," @@ -553,25 +563,30 @@ + "A.TABLE_NAME AS FKTABLE_NAME," + "A.COLUMN_NAME AS FKCOLUMN_NAME, " + "A.ORDINAL_POSITION AS KEY_SEQ," - + importedKeyRestrict + + generateUpdateRuleClause() + " AS UPDATE_RULE," - + importedKeyRestrict + + generateDeleteRuleClause() + " AS DELETE_RULE," + "A.CONSTRAINT_NAME AS FK_NAME," - + "NULL AS PK_NAME," + + "(SELECT CONSTRAINT_NAME FROM" + + " INFORMATION_SCHEMA.TABLE_CONSTRAINTS" + + " WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA AND" + + " TABLE_NAME = A.REFERENCED_TABLE_NAME AND" + + " CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1)" + + " AS PK_NAME," + importedKeyNotDeferrable + " AS DEFERRABILITY " + "FROM " - + "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A," + + "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A JOIN " + "INFORMATION_SCHEMA.TABLE_CONSTRAINTS B " + + "USING (TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME) " + + generateOptionalRefContraintsJoin() + "WHERE " - + "A.TABLE_SCHEMA=B.TABLE_SCHEMA AND A.TABLE_NAME=B.TABLE_NAME " - + "AND " - + "A.CONSTRAINT_NAME=B.CONSTRAINT_NAME AND B.CONSTRAINT_TYPE IS NOT NULL " + + "B.CONSTRAINT_TYPE = 'FOREIGN KEY' " + "AND A.REFERENCED_TABLE_SCHEMA LIKE ? AND A.REFERENCED_TABLE_NAME=? " + "ORDER BY A.TABLE_SCHEMA, A.TABLE_NAME, A.ORDINAL_POSITION"; - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -586,21 +601,7 @@ ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "PKTABLE_CAT", Types.CHAR, 255), - new Field("", "PKTABLE_SCHEM", Types.CHAR, 0), - new Field("", "PKTABLE_NAME", Types.CHAR, 255), - new Field("", "PKCOLUMN_NAME", Types.CHAR, 32), - new Field("", "FKTABLE_CAT", Types.CHAR, 255), - new Field("", "FKTABLE_SCHEM", Types.CHAR, 0), - new Field("", "FKTABLE_NAME", Types.CHAR, 255), - new Field("", "FKCOLUMN_NAME", Types.CHAR, 32), - new Field("", "KEY_SEQ", Types.SMALLINT, 2), - new Field("", "UPDATE_RULE", Types.SMALLINT, 2), - new Field("", "DELETE_RULE", Types.SMALLINT, 2), - new Field("", "FK_NAME", Types.CHAR, 255), - new Field("", "PK_NAME", Types.CHAR, 0), - new Field("", "DEFERRABILITY", Types.INTEGER, 2) }); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createFkMetadataFields()); return rs; } finally { @@ -611,32 +612,34 @@ } - /* - * - * getTablePrivileges - * - * if (getMysqlVersion() > 49999) { if (!strcasecmp("localhost", - * m_pSettings->pConnection->host)) { sprintf(user, "A.GRANTEE = - * \"'%s'@'localhost'\" OR A.GRANTEE LIKE \"'%'@'localhost'\"", - * m_pSettings->pConnection->user, m_pSettings->pConnection->user); } else { - * sprintf(user, "\"'%s'@'%s'\" LIKE A.GRANTEE", - * m_pSettings->pConnection->user, m_pSettings->pConnection->host); } - * - * sprintf(query, "SELECT DISTINCT A.TABLE_CATALOG, B.TABLE_SCHEMA, - * B.TABLE_NAME, CURRENT_USER(), " \ "A.PRIVILEGE_TYPE FROM - * INFORMATION_SCHEMA.USER_PRIVILEGES A, INFORMATION_SCHEMA.TABLES B " \ - * "WHERE B.TABLE_SCHEMA LIKE '%s' AND B.TABLE_NAME LIKE '%s' AND (%s) " \ - * "UNION " \ "SELECT DISTINCT A.TABLE_CATALOG, B.TABLE_SCHEMA, - * B.TABLE_NAME, CURRENT_USER(), A.PRIVILEGE_TYPE " \ "FROM - * INFORMATION_SCHEMA.SCHEMA_PRIVILEGES A, INFORMATION_SCHEMA.TABLES B WHERE " \ - * "B.TABLE_SCHEMA LIKE '%s' AND B.TABLE_NAME LIKE '%s' AND (%s) " \ "UNION "\ - * "SELECT DISTINCT A.TABLE_CATALOG, A.TABLE_SCHEMA, A.TABLE_NAME, - * CURRENT_USER, A.PRIVILEGE_TYPE FROM " \ - * "INFORMATION_SCHEMA.TABLE_PRIVILEGES A WHERE A.TABLE_SCHEMA LIKE '%s' AND - * A.TABLE_NAME LIKE '%s' " \ "AND (%s)", schemaName, tableName, user, - * schemaName, tableName, user, schemaName, tableName, user ); - */ + private String generateOptionalRefContraintsJoin() { + return ((this.hasReferentialConstraintsView) ? "JOIN " + + "INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R " + + "ON (R.CONSTRAINT_NAME = B.CONSTRAINT_NAME " + + "AND R.TABLE_NAME = B.TABLE_NAME AND " + + "R.CONSTRAINT_SCHEMA = B.TABLE_SCHEMA) " : ""); + } + private String generateDeleteRuleClause() { + return ((this.hasReferentialConstraintsView) ? + "CASE WHEN R.DELETE_RULE='CASCADE' THEN " + String.valueOf(importedKeyCascade) + + " WHEN R.DELETE_RULE='SET NULL' THEN " + String.valueOf(importedKeySetNull) + + " WHEN R.DELETE_RULE='SET DEFAULT' THEN " + String.valueOf(importedKeySetDefault) + + " WHEN R.DELETE_RULE='RESTRICT' THEN " + String.valueOf(importedKeyRestrict) + + " WHEN R.DELETE_RULE='NO ACTION' THEN " + String.valueOf(importedKeyNoAction) + + " ELSE " + String.valueOf(importedKeyNoAction) + " END " : String.valueOf(importedKeyRestrict)); + } + + private String generateUpdateRuleClause() { + return ((this.hasReferentialConstraintsView) ? + "CASE WHEN R.UPDATE_RULE='CASCADE' THEN " + String.valueOf(importedKeyCascade) + + " WHEN R.UPDATE_RULE='SET NULL' THEN " + String.valueOf(importedKeySetNull) + + " WHEN R.UPDATE_RULE='SET DEFAULT' THEN " + String.valueOf(importedKeySetDefault) + + " WHEN R.UPDATE_RULE='RESTRICT' THEN " + String.valueOf(importedKeyRestrict) + + " WHEN R.UPDATE_RULE='NO ACTION' THEN " + String.valueOf(importedKeyNoAction) + + " ELSE " + String.valueOf(importedKeyNoAction) + " END " : String.valueOf(importedKeyRestrict)); + } + /** * Get a description of the primary key columns that are referenced by a * table's foreign key columns (the primary keys imported by a table). They @@ -700,7 +703,7 @@ String table) throws SQLException { if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } if (catalog == null) { @@ -719,25 +722,34 @@ + "A.TABLE_NAME AS FKTABLE_NAME, " + "A.COLUMN_NAME AS FKCOLUMN_NAME, " + "A.ORDINAL_POSITION AS KEY_SEQ," - + importedKeyRestrict + + generateUpdateRuleClause() + " AS UPDATE_RULE," - + importedKeyRestrict + + generateDeleteRuleClause() + " AS DELETE_RULE," + "A.CONSTRAINT_NAME AS FK_NAME," - + "NULL AS PK_NAME, " + + "(SELECT CONSTRAINT_NAME FROM" + + " INFORMATION_SCHEMA.TABLE_CONSTRAINTS" + + " WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA AND" + + " TABLE_NAME = A.REFERENCED_TABLE_NAME AND" + + " CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1)" + + " AS PK_NAME," + importedKeyNotDeferrable + " AS DEFERRABILITY " + "FROM " - + "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A, " - + "INFORMATION_SCHEMA.TABLE_CONSTRAINTS B WHERE A.TABLE_SCHEMA LIKE ? " - + "AND A.CONSTRAINT_NAME=B.CONSTRAINT_NAME AND A.TABLE_NAME=? " - + "AND " - + "B.TABLE_NAME=? AND A.REFERENCED_TABLE_SCHEMA IS NOT NULL " - + " ORDER BY " + + "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A " + + "JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B USING " + + "(CONSTRAINT_NAME, TABLE_NAME) " + + generateOptionalRefContraintsJoin() + + "WHERE " + + "B.CONSTRAINT_TYPE = 'FOREIGN KEY' " + + "AND A.TABLE_SCHEMA LIKE ? " + + "AND A.TABLE_NAME=? " + + "AND A.REFERENCED_TABLE_SCHEMA IS NOT NULL " + + "ORDER BY " + "A.REFERENCED_TABLE_SCHEMA, A.REFERENCED_TABLE_NAME, " + "A.ORDINAL_POSITION"; - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -749,25 +761,10 @@ } pStmt.setString(2, table); - pStmt.setString(3, table); ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "PKTABLE_CAT", Types.CHAR, 255), - new Field("", "PKTABLE_SCHEM", Types.CHAR, 0), - new Field("", "PKTABLE_NAME", Types.CHAR, 255), - new Field("", "PKCOLUMN_NAME", Types.CHAR, 32), - new Field("", "FKTABLE_CAT", Types.CHAR, 255), - new Field("", "FKTABLE_SCHEM", Types.CHAR, 0), - new Field("", "FKTABLE_NAME", Types.CHAR, 255), - new Field("", "FKCOLUMN_NAME", Types.CHAR, 32), - new Field("", "KEY_SEQ", Types.SMALLINT, 2), - new Field("", "UPDATE_RULE", Types.SMALLINT, 2), - new Field("", "DELETE_RULE", Types.SMALLINT, 2), - new Field("", "FK_NAME", Types.CHAR, 255), - new Field("", "PK_NAME", Types.CHAR, 0), - new Field("", "DEFERRABILITY", Types.INTEGER, 2) }); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createFkMetadataFields()); return rs; } finally { @@ -854,7 +851,7 @@ sqlBuf.append("ORDER BY NON_UNIQUE, INDEX_NAME, SEQ_IN_INDEX"); - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { if (catalog == null) { @@ -875,20 +872,7 @@ ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "TABLE_CAT", Types.CHAR, 255), - new Field("", "TABLE_SCHEM", Types.CHAR, 0), - new Field("", "TABLE_NAME", Types.CHAR, 255), - new Field("", "NON_UNIQUE", Types.CHAR, 4), - new Field("", "INDEX_QUALIFIER", Types.CHAR, 1), - new Field("", "INDEX_NAME", Types.CHAR, 32), - new Field("", "TYPE", Types.CHAR, 32), - new Field("", "ORDINAL_POSITION", Types.SMALLINT, 5), - new Field("", "COLUMN_NAME", Types.CHAR, 32), - new Field("", "ASC_OR_DESC", Types.CHAR, 1), - new Field("", "CARDINALITY", Types.INTEGER, 10), - new Field("", "PAGES", Types.INTEGER, 10), - new Field("", "FILTER_CONDITION", Types.CHAR, 32) }); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createIndexInfoFields()); return rs; } finally { @@ -934,15 +918,15 @@ if (table == null) { throw SQLError.createSQLException("Table not specified.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } String sql = "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, " + "COLUMN_NAME, SEQ_IN_INDEX AS KEY_SEQ, 'PRIMARY' AS PK_NAME FROM INFORMATION_SCHEMA.STATISTICS " + "WHERE TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ? AND " + "INDEX_NAME='PRIMARY' ORDER BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX"; - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -956,7 +940,7 @@ pStmt.setString(2, table); ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(new Field[] { new Field("", "TABLE_CAT", Types.CHAR, 255), new Field("", "TABLE_SCHEM", Types.CHAR, 0), new Field("", "TABLE_NAME", Types.CHAR, 255), @@ -1022,7 +1006,7 @@ } else { throw SQLError.createSQLException( "Procedure name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @@ -1032,6 +1016,8 @@ if (this.conn.getNullCatalogMeansCurrent()) { db = this.database; } + } else { + db = catalog; } String sql = "SELECT ROUTINE_SCHEMA AS PROCEDURE_CAT, " @@ -1042,12 +1028,14 @@ + "CASE WHEN ROUTINE_TYPE = 'PROCEDURE' THEN " + procedureNoResult + " WHEN ROUTINE_TYPE='FUNCTION' THEN " + procedureReturnsResult + " ELSE " + procedureResultUnknown - + " END AS PROCEDURE_TYPE " + + " END AS PROCEDURE_TYPE, " + + "ROUTINE_NAME AS SPECIFIC_NAME " + "FROM INFORMATION_SCHEMA.ROUTINES WHERE " + + getRoutineTypeConditionForGetProcedures() + "ROUTINE_SCHEMA LIKE ? AND ROUTINE_NAME LIKE ? " - + "ORDER BY ROUTINE_SCHEMA, ROUTINE_NAME"; + + "ORDER BY ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE"; - PreparedStatement pStmt = null; + java.sql.PreparedStatement pStmt = null; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -1061,15 +1049,7 @@ pStmt.setString(2, procedureNamePattern); ResultSet rs = executeMetadataQuery(pStmt); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "PROCEDURE_CAT", Types.CHAR, 0), - new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0), - new Field("", "PROCEDURE_NAME", Types.CHAR, 0), - new Field("", "reserved1", Types.CHAR, 0), - new Field("", "reserved2", Types.CHAR, 0), - new Field("", "reserved3", Types.CHAR, 0), - new Field("", "REMARKS", Types.CHAR, 0), - new Field("", "PROCEDURE_TYPE", Types.SMALLINT, 0) }); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createFieldMetadataForGetProcedures()); return rs; } finally { @@ -1080,6 +1060,216 @@ } /** + * Returns a condition to be injected in the query that returns metadata for procedures only. Overridden by + * subclasses when needed. When not empty must end with "AND ". + * + * @return String with the condition to be injected. + */ + protected String getRoutineTypeConditionForGetProcedures() { + return ""; + } + + /** + * Retrieves a description of the given catalog's stored procedure parameter + * and result columns. + * + *

Only descriptions matching the schema, procedure and + * parameter name criteria are returned. They are ordered by + * PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value, + * if any, is first. Next are the parameter descriptions in call + * order. The column descriptions follow in column number order. + * + *

Each row in the ResultSet is a parameter description or + * column description with the following fields: + *

    + *
  1. PROCEDURE_CAT String => procedure catalog (may be null) + *
  2. PROCEDURE_SCHEM String => procedure schema (may be null) + *
  3. PROCEDURE_NAME String => procedure name + *
  4. COLUMN_NAME String => column/parameter name + *
  5. COLUMN_TYPE Short => kind of column/parameter: + *
      + *
    • procedureColumnUnknown - nobody knows + *
    • procedureColumnIn - IN parameter + *
    • procedureColumnInOut - INOUT parameter + *
    • procedureColumnOut - OUT parameter + *
    • procedureColumnReturn - procedure return value + *
    • procedureColumnResult - result column in ResultSet + *
    + *
  6. DATA_TYPE int => SQL type from java.sql.Types + *
  7. TYPE_NAME String => SQL type name, for a UDT type the + * type name is fully qualified + *
  8. PRECISION int => precision + *
  9. LENGTH int => length in bytes of data + *
  10. SCALE short => scale + *
  11. RADIX short => radix + *
  12. NULLABLE short => can it contain NULL. + *
      + *
    • procedureNoNulls - does not allow NULL values + *
    • procedureNullable - allows NULL values + *
    • procedureNullableUnknown - nullability unknown + *
    + *
  13. REMARKS String => comment describing parameter/column + *
+ * + *

Note: Some databases may not return the column + * descriptions for a procedure. Additional columns beyond + * REMARKS can be defined by the database. + * + * @param catalog a catalog name; must match the catalog name as it + * is stored in the database; "" retrieves those without a catalog; + * null means that the catalog name should not be used to narrow + * the search + * @param schemaPattern a schema name pattern; must match the schema name + * as it is stored in the database; "" retrieves those without a schema; + * null means that the schema name should not be used to narrow + * the search + * @param procedureNamePattern a procedure name pattern; must match the + * procedure name as it is stored in the database + * @param columnNamePattern a column name pattern; must match the column name + * as it is stored in the database + * @return ResultSet - each row describes a stored procedure parameter or + * column + * @exception SQLException if a database access error occurs + * @see #getSearchStringEscape + */ + public ResultSet getProcedureColumns(String catalog, String schemaPattern, + String procedureNamePattern, String columnNamePattern) + throws SQLException { + if (!this.hasParametersView) { + return getProcedureColumnsNoISParametersView(catalog, schemaPattern, procedureNamePattern, columnNamePattern); + } + + if ((procedureNamePattern == null) + || (procedureNamePattern.length() == 0)) { + if (this.conn.getNullNamePatternMatchesAll()) { + procedureNamePattern = "%"; + } else { + throw SQLError.createSQLException( + "Procedure name pattern can not be NULL or empty.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + String db = null; + + if (catalog == null) { + if (this.conn.getNullCatalogMeansCurrent()) { + db = this.database; + } + } else { + db = catalog; + } + + // Here's what we get from MySQL ... + // SPECIFIC_CATALOG NULL + // SPECIFIC_SCHEMA db17 + // SPECIFIC_NAME p + // ORDINAL_POSITION 1 + // PARAMETER_MODE OUT + // PARAMETER_NAME a + // DATA_TYPE int + // CHARACTER_MAXIMUM_LENGTH NULL + // CHARACTER_OCTET_LENGTH NULL + // CHARACTER_SET_NAME NULL + // COLLATION_NAME NULL + // NUMERIC_PRECISION 10 + // NUMERIC_SCALE 0 + // DTD_IDENTIFIER int(11) + + StringBuffer sqlBuf = new StringBuffer("SELECT SPECIFIC_SCHEMA AS PROCEDURE_CAT, " + + "NULL AS `PROCEDURE_SCHEM`, " + + "SPECIFIC_NAME AS `PROCEDURE_NAME`, " + + "IFNULL(PARAMETER_NAME, '') AS `COLUMN_NAME`, " + + "CASE WHEN PARAMETER_MODE = 'IN' THEN " + procedureColumnIn + + " WHEN PARAMETER_MODE = 'OUT' THEN " + procedureColumnOut + + " WHEN PARAMETER_MODE = 'INOUT' THEN " + procedureColumnInOut + + " WHEN ORDINAL_POSITION = 0 THEN " + procedureColumnReturn + + " ELSE " + procedureColumnUnknown + + " END AS `COLUMN_TYPE`, "); + + //DATA_TYPE + MysqlDefs.appendJdbcTypeMappingQuery(sqlBuf, "DATA_TYPE"); + + sqlBuf.append(" AS `DATA_TYPE`, "); + + // TYPE_NAME + if (conn.getCapitalizeTypeNames()) { + sqlBuf.append("UPPER(CASE WHEN LOCATE('unsigned', DATA_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END) AS `TYPE_NAME`,"); + } else { + sqlBuf.append("CASE WHEN LOCATE('unsigned', DATA_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END AS `TYPE_NAME`,"); + } + + // PRECISION int => precision + sqlBuf.append("NUMERIC_PRECISION AS `PRECISION`, "); + // LENGTH int => length in bytes of data + sqlBuf + .append("CASE WHEN LCASE(DATA_TYPE)='date' THEN 10 WHEN LCASE(DATA_TYPE)='time' THEN 8 WHEN LCASE(DATA_TYPE)='datetime' THEN 19 WHEN LCASE(DATA_TYPE)='timestamp' THEN 19 WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION WHEN CHARACTER_MAXIMUM_LENGTH > " + + Integer.MAX_VALUE + " THEN " + Integer.MAX_VALUE + " ELSE CHARACTER_MAXIMUM_LENGTH END AS LENGTH, "); + + // SCALE short => scale + sqlBuf.append("NUMERIC_SCALE AS `SCALE`, "); + // RADIX short => radix + sqlBuf.append("10 AS RADIX,"); + sqlBuf.append(procedureNullable + " AS `NULLABLE`, " + + "NULL AS `REMARKS`, " + + "NULL AS `COLUMN_DEF`, " + + "NULL AS `SQL_DATA_TYPE`, " + + "NULL AS `SQL_DATETIME_SUB`, " + + "CHARACTER_OCTET_LENGTH AS `CHAR_OCTET_LENGTH`, " + + "ORDINAL_POSITION, " + + "'YES' AS `IS_NULLABLE`, " + + "SPECIFIC_NAME " + + "FROM INFORMATION_SCHEMA.PARAMETERS WHERE " + + getRoutineTypeConditionForGetProcedureColumns() + + "SPECIFIC_SCHEMA LIKE ? AND SPECIFIC_NAME LIKE ? AND (PARAMETER_NAME LIKE ? OR PARAMETER_NAME IS NULL) " + + "ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ROUTINE_TYPE, ORDINAL_POSITION"); + + java.sql.PreparedStatement pStmt = null; + + try { + pStmt = prepareMetaDataSafeStatement(sqlBuf.toString()); + + if (db != null) { + pStmt.setString(1, db); + } else { + pStmt.setString(1, "%"); + } + + pStmt.setString(2, procedureNamePattern); + pStmt.setString(3, columnNamePattern); + + ResultSet rs = executeMetadataQuery(pStmt); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createProcedureColumnsFields()); + + return rs; + } finally { + if (pStmt != null) { + pStmt.close(); + } + } + } + + /** + * Redirects to another implementation of #getProcedureColumns. Subclasses may need to override this method. + * + * @see getProcedureColumns + */ + protected ResultSet getProcedureColumnsNoISParametersView(String catalog, String schemaPattern, + String procedureNamePattern, String columnNamePattern) throws SQLException { + return super.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern); + } + + /** + * Returns a condition to be injected in the query that returns metadata for procedure columns only. Overridden by + * subclasses when needed. When not empty must end with "AND ". + * + * @return String with the condition to be injected. + */ + protected String getRoutineTypeConditionForGetProcedureColumns() { + return ""; + } + + /** * Get a description of tables available in a catalog. *

* Only table descriptions matching the catalog, schema, table name and type @@ -1129,19 +1319,65 @@ } else { throw SQLError.createSQLException( "Table name pattern can not be NULL or empty.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } - PreparedStatement pStmt = null; + final String tableNamePat; + String tmpCat = ""; + + if ((catalog == null) || (catalog.length() == 0)) { + if (this.conn.getNullCatalogMeansCurrent()) { + tmpCat = this.database; + } + } else { + tmpCat = catalog; + } + + List parseList = StringUtils.splitDBdotName(tableNamePattern, tmpCat, + quotedId , conn.isNoBackslashEscapesSet()); + //There *should* be 2 rows, if any. + if (parseList.size() == 2) { + tableNamePat = parseList.get(1); + } else { + tableNamePat = tableNamePattern; + } + java.sql.PreparedStatement pStmt = null; + String sql = "SELECT TABLE_SCHEMA AS TABLE_CAT, " + "NULL AS TABLE_SCHEM, TABLE_NAME, " - + "CASE WHEN TABLE_TYPE='BASE TABLE' THEN 'TABLE' WHEN TABLE_TYPE='TEMPORARY' THEN 'LOCAL_TEMPORARY' ELSE TABLE_TYPE END AS TABLE_TYPE, " - + "TABLE_COMMENT AS REMARKS " - + "FROM INFORMATION_SCHEMA.TABLES WHERE " - + "TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ? AND TABLE_TYPE IN (?,?,?) " - + "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME"; + + "CASE WHEN TABLE_TYPE='BASE TABLE' THEN CASE WHEN TABLE_SCHEMA = 'mysql' OR TABLE_SCHEMA = 'performance_schema' THEN 'SYSTEM TABLE' ELSE 'TABLE' END " + + "WHEN TABLE_TYPE='TEMPORARY' THEN 'LOCAL_TEMPORARY' ELSE TABLE_TYPE END AS TABLE_TYPE, " + + "TABLE_COMMENT AS REMARKS, NULL AS TYPE_CAT, NULL AS TYPE_SCHEM, NULL AS TYPE_NAME, NULL AS SELF_REFERENCING_COL_NAME, NULL AS REF_GENERATION " + + "FROM INFORMATION_SCHEMA.TABLES WHERE "; + + final boolean operatingOnInformationSchema = "information_schema".equalsIgnoreCase(catalog); + if (catalog != null) { + if ((operatingOnInformationSchema) || ((StringUtils.indexOfIgnoreCase(0, catalog, "%") == -1) + && (StringUtils.indexOfIgnoreCase(0, catalog, "_") == -1))) { + sql += "TABLE_SCHEMA = ? "; + } else { + sql += "TABLE_SCHEMA LIKE ? "; + } + + } else { + sql += "TABLE_SCHEMA LIKE ? "; + } + + if (tableNamePat != null) { + if ((StringUtils.indexOfIgnoreCase(0, tableNamePat, "%") == -1) + && (StringUtils.indexOfIgnoreCase(0, tableNamePat, "_") == -1)) { + sql += "AND TABLE_NAME = ? "; + } else { + sql += "AND TABLE_NAME LIKE ? "; + } + + } else { + sql += "AND TABLE_NAME LIKE ? "; + } + sql = sql + "HAVING TABLE_TYPE IN (?,?,?,?,?) "; + sql = sql + "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME"; try { pStmt = prepareMetaDataSafeStatement(sql); @@ -1151,44 +1387,311 @@ pStmt.setString(1, "%"); } - pStmt.setString(2, tableNamePattern); + pStmt.setString(2, tableNamePat); // This overloading of IN (...) allows us to cache this // prepared statement if (types == null || types.length == 0) { - pStmt.setString(3, "BASE TABLE"); - pStmt.setString(4, "VIEW"); - pStmt.setString(5, "TEMPORARY"); + TableType[] tableTypes = TableType.values(); + for (int i = 0; i < 5; i++) { + pStmt.setString(3 + i, tableTypes[i].getName()); + } } else { - pStmt.setNull(3, Types.VARCHAR); - pStmt.setNull(4, Types.VARCHAR); - pStmt.setNull(5, Types.VARCHAR); + for (int i = 0; i < 5; i++) { + pStmt.setNull(3 + i, Types.VARCHAR); + } + int idx = 3; for (int i = 0; i < types.length; i++) { - if ("TABLE".equalsIgnoreCase(types[i])) { - pStmt.setString(3, "BASE TABLE"); + TableType tableType = TableType.getTableTypeEqualTo(types[i]); + if (tableType != TableType.UNKNOWN) { + pStmt.setString(idx++, tableType.getName()); } + } + } - if ("VIEW".equalsIgnoreCase(types[i])) { - pStmt.setString(4, "VIEW"); - } + ResultSet rs = executeMetadataQuery(pStmt); - if ("LOCAL TEMPORARY".equalsIgnoreCase(types[i])) { - pStmt.setString(5, "TEMPORARY"); - } - } + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createTablesFields()); + + return rs; + } finally { + if (pStmt != null) { + pStmt.close(); } + } + } + + public boolean gethasParametersView() { + return this.hasParametersView; + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, + String table) throws SQLException { + + if (catalog == null) { + if (this.conn.getNullCatalogMeansCurrent()) { + catalog = this.database; + } + } + + if (table == null) { + throw SQLError.createSQLException("Table not specified.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + StringBuffer sqlBuf = new StringBuffer("SELECT NULL AS SCOPE, COLUMN_NAME, "); + + MysqlDefs.appendJdbcTypeMappingQuery(sqlBuf, "DATA_TYPE"); + sqlBuf.append(" AS DATA_TYPE, "); + + sqlBuf.append("COLUMN_TYPE AS TYPE_NAME, "); + sqlBuf.append("CASE WHEN LCASE(DATA_TYPE)='date' THEN 10 WHEN LCASE(DATA_TYPE)='time' THEN 8 " + + "WHEN LCASE(DATA_TYPE)='datetime' THEN 19 WHEN LCASE(DATA_TYPE)='timestamp' THEN 19 " + + "WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION WHEN CHARACTER_MAXIMUM_LENGTH > " + + Integer.MAX_VALUE + " THEN " + Integer.MAX_VALUE + " ELSE CHARACTER_MAXIMUM_LENGTH END AS COLUMN_SIZE, "); + sqlBuf.append( + MysqlIO.getMaxBuf() + " AS BUFFER_LENGTH," + + "NUMERIC_SCALE AS DECIMAL_DIGITS, " + + Integer.toString(java.sql.DatabaseMetaData.versionColumnNotPseudo) + " AS PSEUDO_COLUMN " + + "FROM INFORMATION_SCHEMA.COLUMNS " + + "WHERE TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ?" + + " AND EXTRA LIKE '%on update CURRENT_TIMESTAMP%'"); + + java.sql.PreparedStatement pStmt = null; + + try { + pStmt = prepareMetaDataSafeStatement(sqlBuf.toString()); + + if (catalog != null) { + pStmt.setString(1, catalog); + } else { + pStmt.setString(1, "%"); + } + + pStmt.setString(2, table); + ResultSet rs = executeMetadataQuery(pStmt); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(new Field[] { + new Field("", "SCOPE", Types.SMALLINT, 5), + new Field("", "COLUMN_NAME", Types.CHAR, 32), + new Field("", "DATA_TYPE", Types.INTEGER, 5), + new Field("", "TYPE_NAME", Types.CHAR, 16), + new Field("", "COLUMN_SIZE", Types.INTEGER, 16), + new Field("", "BUFFER_LENGTH", Types.INTEGER, 16), + new Field("", "DECIMAL_DIGITS", Types.SMALLINT, 16), + new Field("", "PSEUDO_COLUMN", Types.SMALLINT, 5) + }); - ((com.mysql.jdbc.ResultSet) rs).redefineFieldsForDBMD(new Field[] { - new Field("", "TABLE_CAT", java.sql.Types.VARCHAR, - (catalog == null) ? 0 : catalog.length()), - new Field("", "TABLE_SCHEM", java.sql.Types.VARCHAR, 0), - new Field("", "TABLE_NAME", java.sql.Types.VARCHAR, 255), - new Field("", "TABLE_TYPE", java.sql.Types.VARCHAR, 5), - new Field("", "REMARKS", java.sql.Types.VARCHAR, 0) }); + return rs; + } finally { + if (pStmt != null) { + pStmt.close(); + } + } + } + // + // JDBC-4.0 functions that aren't reliant on Java6 + // + + /** + * Retrieves a description of the given catalog's system or user + * function parameters and return type. + * + *

Only descriptions matching the schema, function and + * parameter name criteria are returned. They are ordered by + * FUNCTION_CAT, FUNCTION_SCHEM, + * FUNCTION_NAME and + * SPECIFIC_ NAME. Within this, the return value, + * if any, is first. Next are the parameter descriptions in call + * order. The column descriptions follow in column number order. + * + *

Each row in the ResultSet + * is a parameter description, column description or + * return type description with the following fields: + *

    + *
  1. FUNCTION_CAT String => function catalog (may be null) + *
  2. FUNCTION_SCHEM String => function schema (may be null) + *
  3. FUNCTION_NAME String => function name. This is the name + * used to invoke the function + *
  4. COLUMN_NAME String => column/parameter name + *
  5. COLUMN_TYPE Short => kind of column/parameter: + *
      + *
    • functionColumnUnknown - nobody knows + *
    • functionColumnIn - IN parameter + *
    • functionColumnInOut - INOUT parameter + *
    • functionColumnOut - OUT parameter + *
    • functionColumnReturn - function return value + *
    • functionColumnResult - Indicates that the parameter or column + * is a column in the ResultSet + *
    + *
  6. DATA_TYPE int => SQL type from java.sql.Types + *
  7. TYPE_NAME String => SQL type name, for a UDT type the + * type name is fully qualified + *
  8. PRECISION int => precision + *
  9. LENGTH int => length in bytes of data + *
  10. SCALE short => scale - null is returned for data types where + * SCALE is not applicable. + *
  11. RADIX short => radix + *
  12. NULLABLE short => can it contain NULL. + *
      + *
    • functionNoNulls - does not allow NULL values + *
    • functionNullable - allows NULL values + *
    • functionNullableUnknown - nullability unknown + *
    + *
  13. REMARKS String => comment describing column/parameter + *
  14. CHAR_OCTET_LENGTH int => the maximum length of binary + * and character based parameters or columns. For any other datatype the returned value + * is a NULL + *
  15. ORDINAL_POSITION int => the ordinal position, starting + * from 1, for the input and output parameters. A value of 0 + * is returned if this row describes the function's return value. + * For result set columns, it is the + * ordinal position of the column in the result set starting from 1. + *
  16. IS_NULLABLE String => ISO rules are used to determine + * the nullability for a parameter or column. + *
      + *
    • YES --- if the parameter or column can include NULLs + *
    • NO --- if the parameter or column cannot include NULLs + *
    • empty string --- if the nullability for the + * parameter or column is unknown + *
    + *
  17. SPECIFIC_NAME String => the name which uniquely identifies + * this function within its schema. This is a user specified, or DBMS + * generated, name that may be different then the FUNCTION_NAME + * for example with overload functions + *
+ * + *

The PRECISION column represents the specified column size for the given + * parameter or column. + * For numeric data, this is the maximum precision. For character data, this is the length in characters. + * For datetime datatypes, this is the length in characters of the String representation (assuming the + * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype, + * this is the length in bytes. Null is returned for data types where the + * column size is not applicable. + * @param catalog a catalog name; must match the catalog name as it + * is stored in the database; "" retrieves those without a catalog; + * null means that the catalog name should not be used to narrow + * the search + * @param schemaPattern a schema name pattern; must match the schema name + * as it is stored in the database; "" retrieves those without a schema; + * null means that the schema name should not be used to narrow + * the search + * @param functionNamePattern a procedure name pattern; must match the + * function name as it is stored in the database + * @param columnNamePattern a parameter name pattern; must match the + * parameter or column name as it is stored in the database + * @return ResultSet - each row describes a + * user function parameter, column or return type + * + * @exception SQLException if a database access error occurs + * @see #getSearchStringEscape + * @since 1.6 + */ + public ResultSet getFunctionColumns(String catalog, + String schemaPattern, + String functionNamePattern, + String columnNamePattern) throws SQLException { + if (!this.hasParametersView) { + return super.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern); + } + + if ((functionNamePattern == null) + || (functionNamePattern.length() == 0)) { + if (this.conn.getNullNamePatternMatchesAll()) { + functionNamePattern = "%"; + } else { + throw SQLError.createSQLException( + "Procedure name pattern can not be NULL or empty.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + String db = null; + + if (catalog == null) { + if (this.conn.getNullCatalogMeansCurrent()) { + db = this.database; + } + } else { + db = catalog; + } + + // FUNCTION_CAT + // FUNCTION_SCHEM + // FUNCTION_NAME + // COLUMN_NAME + // COLUMN_TYPE + StringBuffer sqlBuf = new StringBuffer("SELECT SPECIFIC_SCHEMA AS FUNCTION_CAT, " + + "NULL AS `FUNCTION_SCHEM`, " + + "SPECIFIC_NAME AS `FUNCTION_NAME`, " + + "IFNULL(PARAMETER_NAME, '') AS `COLUMN_NAME`, " + + "CASE WHEN PARAMETER_MODE = 'IN' THEN " + getJDBC4FunctionConstant(JDBC4FunctionConstant.FUNCTION_COLUMN_IN) + + " WHEN PARAMETER_MODE = 'OUT' THEN " + getJDBC4FunctionConstant(JDBC4FunctionConstant.FUNCTION_COLUMN_OUT) + + " WHEN PARAMETER_MODE = 'INOUT' THEN " + getJDBC4FunctionConstant(JDBC4FunctionConstant.FUNCTION_COLUMN_INOUT) + + " WHEN ORDINAL_POSITION = 0 THEN " + getJDBC4FunctionConstant(JDBC4FunctionConstant.FUNCTION_COLUMN_RETURN) + + " ELSE " + getJDBC4FunctionConstant(JDBC4FunctionConstant.FUNCTION_COLUMN_UNKNOWN) + + " END AS `COLUMN_TYPE`, "); + + //DATA_TYPE + MysqlDefs.appendJdbcTypeMappingQuery(sqlBuf, "DATA_TYPE"); + + sqlBuf.append(" AS `DATA_TYPE`, "); + + // TYPE_NAME + if (conn.getCapitalizeTypeNames()) { + sqlBuf.append("UPPER(CASE WHEN LOCATE('unsigned', DATA_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END) AS `TYPE_NAME`,"); + } else { + sqlBuf.append("CASE WHEN LOCATE('unsigned', DATA_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN CONCAT(DATA_TYPE, ' unsigned') ELSE DATA_TYPE END AS `TYPE_NAME`,"); + } + + // PRECISION int => precision + sqlBuf.append("NUMERIC_PRECISION AS `PRECISION`, "); + // LENGTH int => length in bytes of data + sqlBuf + .append("CASE WHEN LCASE(DATA_TYPE)='date' THEN 10 WHEN LCASE(DATA_TYPE)='time' THEN 8 WHEN LCASE(DATA_TYPE)='datetime' THEN 19 WHEN LCASE(DATA_TYPE)='timestamp' THEN 19 WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION WHEN CHARACTER_MAXIMUM_LENGTH > " + + Integer.MAX_VALUE + " THEN " + Integer.MAX_VALUE + " ELSE CHARACTER_MAXIMUM_LENGTH END AS LENGTH, "); + + // SCALE short => scale + sqlBuf.append("NUMERIC_SCALE AS `SCALE`, "); + // RADIX short => radix + sqlBuf.append("10 AS RADIX,"); + // NULLABLE + // REMARKS + // CHAR_OCTET_LENGTH * + // ORDINAL_POSITION * + // IS_NULLABLE * + // SPECIFIC_NAME * + sqlBuf.append(getJDBC4FunctionConstant(JDBC4FunctionConstant.FUNCTION_NULLABLE) + " AS `NULLABLE`, " + + " NULL AS `REMARKS`, " + + "CHARACTER_OCTET_LENGTH AS `CHAR_OCTET_LENGTH`, " + + " ORDINAL_POSITION, " + + "'YES' AS `IS_NULLABLE`, " + + "SPECIFIC_NAME " + + "FROM INFORMATION_SCHEMA.PARAMETERS WHERE " + + "SPECIFIC_SCHEMA LIKE ? AND SPECIFIC_NAME LIKE ? AND (PARAMETER_NAME LIKE ? OR PARAMETER_NAME IS NULL) " + + "AND ROUTINE_TYPE='FUNCTION' ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION"); + + java.sql.PreparedStatement pStmt = null; + + try { + pStmt = prepareMetaDataSafeStatement(sqlBuf.toString()); + + if (db != null) { + pStmt.setString(1, db); + } else { + pStmt.setString(1, "%"); + } + + pStmt.setString(2, functionNamePattern); + pStmt.setString(3, columnNamePattern); + + ResultSet rs = executeMetadataQuery(pStmt); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(createFunctionColumnsFields()); + return rs; } finally { if (pStmt != null) { @@ -1197,18 +1700,130 @@ } } - private PreparedStatement prepareMetaDataSafeStatement(String sql) - throws SQLException { - // Can't use server-side here as we coerce a lot of types to match - // the spec. - PreparedStatement pStmt = this.conn.clientPrepareStatement(sql); + /** + * Getter to JDBC4 DatabaseMetaData.function* constants. + * This method must be overridden by JDBC4 subclasses. this implementation should never be called. + * + * @param constant + * the constant id from DatabaseMetaData fields to return. + * + * @return 0 + */ + protected int getJDBC4FunctionConstant(JDBC4FunctionConstant constant) { + return 0; + } - if (pStmt.getMaxRows() != 0) { - pStmt.setMaxRows(0); + /** + * Retrieves a description of the system and user functions available + * in the given catalog. + *

+ * Only system and user function descriptions matching the schema and + * function name criteria are returned. They are ordered by + * FUNCTION_CAT, FUNCTION_SCHEM, + * FUNCTION_NAME and + * SPECIFIC_ NAME. + * + *

Each function description has the the following columns: + *

    + *
  1. FUNCTION_CAT String => function catalog (may be null) + *
  2. FUNCTION_SCHEM String => function schema (may be null) + *
  3. FUNCTION_NAME String => function name. This is the name + * used to invoke the function + *
  4. REMARKS String => explanatory comment on the function + *
  5. FUNCTION_TYPE short => kind of function: + *
      + *
    • functionResultUnknown - Cannot determine if a return value + * or table will be returned + *
    • functionNoTable- Does not return a table + *
    • functionReturnsTable - Returns a table + *
    + *
  6. SPECIFIC_NAME String => the name which uniquely identifies + * this function within its schema. This is a user specified, or DBMS + * generated, name that may be different then the FUNCTION_NAME + * for example with overload functions + *
+ *

+ * A user may not have permission to execute any of the functions that are + * returned by getFunctions + * + * @param catalog a catalog name; must match the catalog name as it + * is stored in the database; "" retrieves those without a catalog; + * null means that the catalog name should not be used to narrow + * the search + * @param schemaPattern a schema name pattern; must match the schema name + * as it is stored in the database; "" retrieves those without a schema; + * null means that the schema name should not be used to narrow + * the search + * @param functionNamePattern a function name pattern; must match the + * function name as it is stored in the database + * @return ResultSet - each row is a function description + * @exception SQLException if a database access error occurs + * @see #getSearchStringEscape + * @since 1.6 + */ + public java.sql.ResultSet getFunctions(String catalog, String schemaPattern, + String functionNamePattern) throws SQLException { + + if ((functionNamePattern == null) + || (functionNamePattern.length() == 0)) { + if (this.conn.getNullNamePatternMatchesAll()) { + functionNamePattern = "%"; + } else { + throw SQLError.createSQLException( + "Function name pattern can not be NULL or empty.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } } - pStmt.setHoldResultsOpenOverClose(true); + String db = null; - return pStmt; + if (catalog == null) { + if (this.conn.getNullCatalogMeansCurrent()) { + db = this.database; + } + } else { + db = catalog; + } + + String sql = "SELECT ROUTINE_SCHEMA AS FUNCTION_CAT, NULL AS FUNCTION_SCHEM, " + + "ROUTINE_NAME AS FUNCTION_NAME, ROUTINE_COMMENT AS REMARKS, " + getJDBC4FunctionNoTableConstant() + + " AS FUNCTION_TYPE, ROUTINE_NAME AS SPECIFIC_NAME FROM INFORMATION_SCHEMA.ROUTINES " + + "WHERE ROUTINE_TYPE LIKE 'FUNCTION' AND ROUTINE_SCHEMA LIKE ? AND " + + "ROUTINE_NAME LIKE ? ORDER BY FUNCTION_CAT, FUNCTION_SCHEM, FUNCTION_NAME, SPECIFIC_NAME"; + + java.sql.PreparedStatement pStmt = null; + + try { + pStmt = prepareMetaDataSafeStatement(sql); + + pStmt.setString(1, db != null ? db : "%"); + pStmt.setString(2, functionNamePattern); + + ResultSet rs = executeMetadataQuery(pStmt); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).redefineFieldsForDBMD(new Field[] { + new Field("", "FUNCTION_CAT", Types.CHAR, 255), + new Field("", "FUNCTION_SCHEM", Types.CHAR, 255), + new Field("", "FUNCTION_NAME", Types.CHAR, 255), + new Field("", "REMARKS", Types.CHAR, 255), + new Field("", "FUNCTION_TYPE", Types.SMALLINT, 6), + new Field("", "SPECIFIC_NAME", Types.CHAR, 255) + }); + + return rs; + } finally { + if (pStmt != null) { + pStmt.close(); + } + } } + + /** + * Getter to JDBC4 DatabaseMetaData.functionNoTable constant. + * This method must be overridden by JDBC4 subclasses. this implementation should never be called. + * + * @return 0 + */ + protected int getJDBC4FunctionNoTableConstant() { + return 0; + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/DocsConnectionPropsHelper.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/DocsConnectionPropsHelper.java (.../DocsConnectionPropsHelper.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/DocsConnectionPropsHelper.java (.../DocsConnectionPropsHelper.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,19 +1,36 @@ /* - * Created on Jan 12, 2004 - * - * To change the template for this generated file go to - * Window - Preferences - Java - Code Generation - Code and Comments + Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ + package com.mysql.jdbc; /** * @author mmatthew * - * To change the template for this generated type comment go to Window - - * Preferences - Java - Code Generation - Code and Comments */ -public class DocsConnectionPropsHelper extends ConnectionProperties { +public class DocsConnectionPropsHelper extends ConnectionPropertiesImpl { + static final long serialVersionUID = -1580779062220390294L; + public static void main(String[] args) throws Exception { System.out.println(new DocsConnectionPropsHelper().exposeAsXml()); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Driver.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Driver.java (.../Driver.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Driver.java (.../Driver.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeProcessor.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeProcessor.java (.../EscapeProcessor.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeProcessor.java (.../EscapeProcessor.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,38 +1,32 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ -/** - * EscapeProcessor performs all escape code processing as outlined in the JDBC - * spec by JavaSoft. - */ package com.mysql.jdbc; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; - +import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; @@ -42,13 +36,17 @@ import java.util.StringTokenizer; import java.util.TimeZone; +/** + * EscapeProcessor performs all escape code processing as outlined in the JDBC + * spec by JavaSoft. + */ class EscapeProcessor { - private static Map JDBC_CONVERT_TO_MYSQL_TYPE_MAP; + private static Map JDBC_CONVERT_TO_MYSQL_TYPE_MAP; - private static Map JDBC_NO_CONVERT_TO_MYSQL_EXPRESSION_MAP; + private static Map JDBC_NO_CONVERT_TO_MYSQL_EXPRESSION_MAP; static { - Map tempMap = new HashMap(); + Map tempMap = new HashMap(); tempMap.put("BIGINT", "0 + ?"); tempMap.put("BINARY", "BINARY"); @@ -71,7 +69,7 @@ JDBC_CONVERT_TO_MYSQL_TYPE_MAP = Collections.unmodifiableMap(tempMap); - tempMap = new HashMap(JDBC_CONVERT_TO_MYSQL_TYPE_MAP); + tempMap = new HashMap(JDBC_CONVERT_TO_MYSQL_TYPE_MAP); tempMap.put("BINARY", "CONCAT(?)"); tempMap.put("CHAR", "CONCAT(?)"); @@ -100,8 +98,8 @@ * DOCUMENT ME! */ public static final Object escapeSQL(String sql, - boolean serverSupportsConvertFn, - Connection conn) throws java.sql.SQLException { + boolean serverSupportsConvertFn, MySQLConnection conn) + throws java.sql.SQLException { boolean replaceEscapeSequence = false; String escapeSequence = null; @@ -125,7 +123,7 @@ EscapeTokenizer escapeTokenizer = new EscapeTokenizer(sql); - byte usesVariables = Statement.USES_VARIABLES_FALSE; + byte usesVariables = StatementImpl.USES_VARIABLES_FALSE; boolean callingStoredFunction = false; while (escapeTokenizer.hasMoreTokens()) { @@ -135,8 +133,9 @@ if (token.charAt(0) == '{') { // It's an escape code if (!token.endsWith("}")) { - throw SQLError.createSQLException("Not a valid escape sequence: " - + token); + throw SQLError + .createSQLException("Not a valid escape sequence: " + + token, conn.getExceptionInterceptor()); } if (token.length() > 2) { @@ -157,7 +156,7 @@ } else { remaining = ((EscapeProcessorResult) remainingResults).escapedSql; - if (usesVariables != Statement.USES_VARIABLES_TRUE) { + if (usesVariables != StatementImpl.USES_VARIABLES_TRUE) { usesVariables = ((EscapeProcessorResult) remainingResults).usesVariables; } } @@ -186,16 +185,21 @@ escapeSequence = st.nextToken(); if (escapeSequence.length() < 3) { - newSql.append(token); // it's just part of the query, push possible syntax errors onto server's shoulders + newSql.append(token); // it's just part of the + // query, push possible + // syntax errors onto + // server's shoulders } else { - escapeSequence = escapeSequence.substring(1, - escapeSequence.length() - 1); + escapeSequence.length() - 1); replaceEscapeSequence = true; } } catch (java.util.NoSuchElementException e) { - newSql.append(token); // it's just part of the query, push possible syntax errors onto server's shoulders + newSql.append(token); // it's just part of the + // query, push possible + // syntax errors onto + // server's shoulders } } else if (StringUtils.startsWithIgnoreCase(collapsedToken, "{fn")) { @@ -209,7 +213,7 @@ if (StringUtils.startsWithIgnoreCaseAndWs(fnToken, "convert")) { newSql.append(processConvertToken(fnToken, - serverSupportsConvertFn)); + serverSupportsConvertFn, conn)); } else { // just pass functions right to the DB newSql.append(fnToken); @@ -220,14 +224,17 @@ int endPos = token.lastIndexOf('\''); // no } if ((startPos == -1) || (endPos == -1)) { - newSql.append(token); // it's just part of the query, push possible syntax errors onto server's shoulders + newSql.append(token); // it's just part of the + // query, push possible + // syntax errors onto + // server's shoulders } else { - + String argument = token.substring(startPos, endPos); - + try { - StringTokenizer st = new StringTokenizer(argument, - " -"); + StringTokenizer st = new StringTokenizer( + argument, " -"); String year4 = st.nextToken(); String month2 = st.nextToken(); String day2 = st.nextToken(); @@ -237,199 +244,15 @@ } catch (java.util.NoSuchElementException e) { throw SQLError.createSQLException( "Syntax error for DATE escape sequence '" - + argument + "'", "42000"); + + argument + "'", "42000", conn.getExceptionInterceptor()); } } } else if (StringUtils.startsWithIgnoreCase(collapsedToken, "{ts")) { - int startPos = token.indexOf('\'') + 1; - int endPos = token.lastIndexOf('\''); // no } - - if ((startPos == -1) || (endPos == -1)) { - newSql.append(token); // it's just part of the query, push possible syntax errors onto server's shoulders - } else { - - String argument = token.substring(startPos, endPos); - - try { - StringTokenizer st = new StringTokenizer(argument, - " .-:"); - String year4 = st.nextToken(); - String month2 = st.nextToken(); - String day2 = st.nextToken(); - String hour = st.nextToken(); - String minute = st.nextToken(); - String second = st.nextToken(); - - /* - * For now, we get the fractional seconds part, but - * we don't use it, as MySQL doesn't support it in - * it's TIMESTAMP data type - * - * String fractionalSecond = ""; - * - * if (st.hasMoreTokens()) { fractionalSecond = - * st.nextToken(); } - */ - /* - * Use the full format because number format will - * not work for "between" clauses. - * - * Ref. Mysql Docs - * - * You can specify DATETIME, DATE and TIMESTAMP - * values using any of a common set of formats: - * - * As a string in either 'YYYY-MM-DD HH:MM:SS' or - * 'YY-MM-DD HH:MM:SS' format. - * - * Thanks to Craig Longman for pointing out this bug - */ - if (!conn.getUseTimezone() && !conn.getUseJDBCCompliantTimezoneShift()) { - newSql.append("'").append(year4).append("-") - .append(month2).append("-").append(day2) - .append(" ").append(hour).append(":") - .append(minute).append(":").append(second) - .append("'"); - } else { - Calendar sessionCalendar; - - if (conn != null) { - sessionCalendar = conn.getCalendarInstanceForSessionOrNew(); - } else { - sessionCalendar = new GregorianCalendar(); - sessionCalendar.setTimeZone(TimeZone.getTimeZone("GMT")); - } - - try { - int year4Int = Integer.parseInt(year4); - int month2Int = Integer.parseInt(month2); - int day2Int = Integer.parseInt(day2); - int hourInt = Integer.parseInt(hour); - int minuteInt = Integer.parseInt(minute); - int secondInt = Integer.parseInt(second); - - synchronized (sessionCalendar) { - boolean useGmtMillis = conn.getUseGmtMillisForDatetimes(); - - Timestamp toBeAdjusted = TimeUtil.fastTimestampCreate(useGmtMillis, - useGmtMillis ? Calendar.getInstance(TimeZone.getTimeZone("GMT")): null, - sessionCalendar, - year4Int, - month2Int, - day2Int, - hourInt, - minuteInt, - secondInt, - 0); - - Timestamp inServerTimezone = TimeUtil.changeTimezone( - conn, - sessionCalendar, - null, - toBeAdjusted, - sessionCalendar.getTimeZone(), - conn.getServerTimezoneTZ(), - false); - - - newSql.append("'"); - - String timezoneLiteral = inServerTimezone.toString(); - - int indexOfDot = timezoneLiteral.indexOf("."); - - if (indexOfDot != -1) { - timezoneLiteral = timezoneLiteral.substring(0, indexOfDot); - } - - newSql.append(timezoneLiteral); - } - - newSql.append("'"); - - - } catch (NumberFormatException nfe) { - throw SQLError.createSQLException("Syntax error in TIMESTAMP escape sequence '" - + token + "'.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } - } catch (java.util.NoSuchElementException e) { - throw SQLError.createSQLException( - "Syntax error for TIMESTAMP escape sequence '" - + argument + "'", "42000"); - } - } + processTimestampToken(conn, newSql, token); } else if (StringUtils.startsWithIgnoreCase(collapsedToken, "{t")) { - int startPos = token.indexOf('\'') + 1; - int endPos = token.lastIndexOf('\''); // no } - - if ((startPos == -1) || (endPos == -1)) { - newSql.append(token); // it's just part of the query, push possible syntax errors onto server's shoulders - } else { - - String argument = token.substring(startPos, endPos); - - try { - StringTokenizer st = new StringTokenizer(argument, - " :"); - String hour = st.nextToken(); - String minute = st.nextToken(); - String second = st.nextToken(); - - if (!conn.getUseTimezone()) { - String timeString = "'" + hour + ":" + minute + ":" - + second + "'"; - newSql.append(timeString); - } else { - Calendar sessionCalendar = null; - - if (conn != null) { - sessionCalendar = conn.getCalendarInstanceForSessionOrNew(); - } else { - sessionCalendar = new GregorianCalendar(); - } - - try { - int hourInt = Integer.parseInt(hour); - int minuteInt = Integer.parseInt(minute); - int secondInt = Integer.parseInt(second); - - synchronized (sessionCalendar) { - Time toBeAdjusted = TimeUtil.fastTimeCreate( - sessionCalendar, - hourInt, - minuteInt, - secondInt); - - Time inServerTimezone = TimeUtil.changeTimezone( - conn, - sessionCalendar, - null, - toBeAdjusted, - sessionCalendar.getTimeZone(), - conn.getServerTimezoneTZ(), - false); - - newSql.append("'"); - newSql.append(inServerTimezone.toString()); - newSql.append("'"); - } - - } catch (NumberFormatException nfe) { - throw SQLError.createSQLException("Syntax error in TIMESTAMP escape sequence '" - + token + "'.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } - } catch (java.util.NoSuchElementException e) { - throw SQLError.createSQLException( - "Syntax error for escape sequence '" - + argument + "'", "42000"); - } - } + processTimeToken(conn, newSql, token); } else if (StringUtils.startsWithIgnoreCase(collapsedToken, "{call") || StringUtils.startsWithIgnoreCase(collapsedToken, @@ -438,7 +261,7 @@ int startPos = StringUtils.indexOfIgnoreCase(token, "CALL") + 5; int endPos = token.length() - 1; - + if (StringUtils.startsWithIgnoreCase(collapsedToken, "{?=call")) { callingStoredFunction = true; @@ -449,26 +272,31 @@ newSql.append("CALL "); newSql.append(token.substring(startPos, endPos)); } - + for (int i = endPos - 1; i >= startPos; i--) { char c = token.charAt(i); - + if (Character.isWhitespace(c)) { continue; } - + if (c != ')') { - newSql.append("()"); // handle no-parenthesis no-arg call not supported - // by MySQL parser + newSql.append("()"); // handle no-parenthesis + // no-arg call not + // supported + // by MySQL parser } - + break; } } else if (StringUtils.startsWithIgnoreCase(collapsedToken, "{oj")) { // MySQL already handles this escape sequence // because of ODBC. Cool. newSql.append(token); + } else { + // not an escape code, just part of the query + newSql.append(token); } } else { newSql.append(token); // it's just part of the query @@ -500,17 +328,314 @@ epr.escapedSql = escapedSql; epr.callingStoredFunction = callingStoredFunction; - if (usesVariables != Statement.USES_VARIABLES_TRUE) { + if (usesVariables != StatementImpl.USES_VARIABLES_TRUE) { if (escapeTokenizer.sawVariableUse()) { - epr.usesVariables = Statement.USES_VARIABLES_TRUE; + epr.usesVariables = StatementImpl.USES_VARIABLES_TRUE; } else { - epr.usesVariables = Statement.USES_VARIABLES_FALSE; + epr.usesVariables = StatementImpl.USES_VARIABLES_FALSE; } } return epr; } + private static void processTimeToken(MySQLConnection conn, + StringBuffer newSql, String token) throws SQLException { + int startPos = token.indexOf('\'') + 1; + int endPos = token.lastIndexOf('\''); // no } + + if ((startPos == -1) || (endPos == -1)) { + newSql.append(token); // it's just part of the + // query, push possible + // syntax errors onto + // server's shoulders + } else { + + String argument = token.substring(startPos, endPos); + + try { + StringTokenizer st = new StringTokenizer( + argument, " :."); + String hour = st.nextToken(); + String minute = st.nextToken(); + String second = st.nextToken(); + + boolean serverSupportsFractionalSecond = false; + String fractionalSecond = ""; + + if (st.hasMoreTokens()) { + if (conn.versionMeetsMinimum(5, 6, 4)) { + serverSupportsFractionalSecond = true; + fractionalSecond = "."+st.nextToken(); + } + } + + if (conn != null && (!conn.getUseTimezone() || !conn.getUseLegacyDatetimeCode())) { + newSql.append("'"); + newSql.append(hour); + newSql.append(":"); + newSql.append(minute); + newSql.append(":"); + newSql.append(second); + newSql.append(fractionalSecond); + newSql.append("'"); + } else { + Calendar sessionCalendar = null; + + if (conn != null) { + sessionCalendar = conn + .getCalendarInstanceForSessionOrNew(); + } else { + sessionCalendar = new GregorianCalendar(); + } + + try { + int hourInt = Integer.parseInt(hour); + int minuteInt = Integer + .parseInt(minute); + int secondInt = Integer + .parseInt(second); + + synchronized (sessionCalendar) { + Time toBeAdjusted = TimeUtil + .fastTimeCreate( + sessionCalendar, + hourInt, minuteInt, + secondInt, conn.getExceptionInterceptor()); + + Time inServerTimezone = TimeUtil + .changeTimezone( + conn, + sessionCalendar, + null, + toBeAdjusted, + sessionCalendar + .getTimeZone(), + conn + .getServerTimezoneTZ(), + false); + + newSql.append("'"); + newSql.append(inServerTimezone + .toString()); + + if (serverSupportsFractionalSecond) { + newSql.append(fractionalSecond); + } + + newSql.append("'"); + } + + } catch (NumberFormatException nfe) { + throw SQLError + .createSQLException( + "Syntax error in TIMESTAMP escape sequence '" + + token + "'.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, conn.getExceptionInterceptor()); + } + } + } catch (java.util.NoSuchElementException e) { + throw SQLError.createSQLException( + "Syntax error for escape sequence '" + + argument + "'", "42000", conn.getExceptionInterceptor()); + } + } + } + + private static void processTimestampToken(MySQLConnection conn, + StringBuffer newSql, String token) throws SQLException { + int startPos = token.indexOf('\'') + 1; + int endPos = token.lastIndexOf('\''); // no } + + if ((startPos == -1) || (endPos == -1)) { + newSql.append(token); // it's just part of the + // query, push possible + // syntax errors onto + // server's shoulders + } else { + + String argument = token.substring(startPos, endPos); + + try { + if (conn != null && !conn.getUseLegacyDatetimeCode()) { + Timestamp ts = Timestamp.valueOf(argument); + SimpleDateFormat tsdf = new SimpleDateFormat( + "''yyyy-MM-dd HH:mm:ss", Locale.US); //$NON-NLS-1$ + + tsdf + .setTimeZone(conn + .getServerTimezoneTZ()); + + newSql.append(tsdf.format(ts)); + + if (ts.getNanos() > 0 && conn.versionMeetsMinimum(5, 6, 4)) { + newSql.append('.'); + newSql.append(TimeUtil.formatNanos(ts.getNanos(), true, true)); + } + + newSql.append('\''); + + } else { + StringTokenizer st = new StringTokenizer( + argument, " .-:"); + try { + String year4 = st.nextToken(); + String month2 = st.nextToken(); + String day2 = st.nextToken(); + String hour = st.nextToken(); + String minute = st.nextToken(); + String second = st.nextToken(); + + boolean serverSupportsFractionalSecond = false; + String fractionalSecond = ""; + if (st.hasMoreTokens()) { + if (conn.versionMeetsMinimum(5, 6, 4)) { + serverSupportsFractionalSecond = true; + fractionalSecond = "."+st.nextToken(); + } + } + + /* + * Use the full format because number + * format will not work for "between" + * clauses. + * + * Ref. Mysql Docs + * + * You can specify DATETIME, DATE and + * TIMESTAMP values using any of a + * common set of formats: + * + * As a string in either 'YYYY-MM-DD + * HH:MM:SS' or 'YY-MM-DD HH:MM:SS' + * format. + * + * Thanks to Craig Longman for pointing + * out this bug + */ + + if (conn != null && + !conn.getUseTimezone() + && !conn.getUseJDBCCompliantTimezoneShift()) { + newSql.append("'").append(year4) + .append("-").append(month2) + .append("-").append(day2) + .append(" ").append(hour) + .append(":").append(minute) + .append(":").append(second) + .append(fractionalSecond) + .append("'"); + } else { + Calendar sessionCalendar; + + if (conn != null) { + sessionCalendar = conn + .getCalendarInstanceForSessionOrNew(); + } else { + sessionCalendar = new GregorianCalendar(); + sessionCalendar + .setTimeZone(TimeZone + .getTimeZone("GMT")); + } + + try { + int year4Int = Integer + .parseInt(year4); + int month2Int = Integer + .parseInt(month2); + int day2Int = Integer + .parseInt(day2); + int hourInt = Integer + .parseInt(hour); + int minuteInt = Integer + .parseInt(minute); + int secondInt = Integer + .parseInt(second); + + synchronized (sessionCalendar) { + boolean useGmtMillis = conn + .getUseGmtMillisForDatetimes(); + + Timestamp toBeAdjusted = TimeUtil + .fastTimestampCreate( + useGmtMillis, + useGmtMillis ? Calendar + .getInstance(TimeZone + .getTimeZone("GMT")) + : null, + sessionCalendar, + year4Int, + month2Int, + day2Int, + hourInt, + minuteInt, + secondInt, + 0); + + Timestamp inServerTimezone = TimeUtil + .changeTimezone( + conn, + sessionCalendar, + null, + toBeAdjusted, + sessionCalendar + .getTimeZone(), + conn + .getServerTimezoneTZ(), + false); + + newSql.append("'"); + + String timezoneLiteral = inServerTimezone + .toString(); + + int indexOfDot = timezoneLiteral + .indexOf("."); + + if (indexOfDot != -1) { + timezoneLiteral = timezoneLiteral + .substring(0, + indexOfDot); + } + + newSql + .append(timezoneLiteral); + } + + if (serverSupportsFractionalSecond) { + newSql.append(fractionalSecond); + } + newSql.append("'"); + + } catch (NumberFormatException nfe) { + throw SQLError + .createSQLException( + "Syntax error in TIMESTAMP escape sequence '" + + token + + "'.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, conn.getExceptionInterceptor()); + } + } + } catch (java.util.NoSuchElementException e) { + throw SQLError.createSQLException( + "Syntax error for TIMESTAMP escape sequence '" + + argument + "'", + "42000", conn.getExceptionInterceptor()); + } + } + } catch (IllegalArgumentException illegalArgumentException) { + SQLException sqlEx = SQLError + .createSQLException( + "Syntax error for TIMESTAMP escape sequence '" + + argument + "'", + "42000", conn.getExceptionInterceptor()); + sqlEx.initCause(illegalArgumentException); + + throw sqlEx; + } + } + } + /** * Re-writes {fn convert (expr, type)} as cast(expr AS type) * @@ -519,7 +644,7 @@ * @throws SQLException */ private static String processConvertToken(String functionToken, - boolean serverSupportsConvertFn) throws SQLException { + boolean serverSupportsConvertFn, MySQLConnection conn) throws SQLException { // The JDBC spec requires these types: // // BIGINT @@ -554,30 +679,31 @@ int firstIndexOfParen = functionToken.indexOf("("); if (firstIndexOfParen == -1) { - throw SQLError.createSQLException( - "Syntax error while processing {fn convert (... , ...)} token, missing opening parenthesis in token '" - + functionToken + "'.", - SQLError.SQL_STATE_SYNTAX_ERROR); + throw SQLError + .createSQLException( + "Syntax error while processing {fn convert (... , ...)} token, missing opening parenthesis in token '" + + functionToken + "'.", + SQLError.SQL_STATE_SYNTAX_ERROR, conn.getExceptionInterceptor()); } - int tokenLength = functionToken.length(); - int indexOfComma = functionToken.lastIndexOf(","); if (indexOfComma == -1) { - throw SQLError.createSQLException( - "Syntax error while processing {fn convert (... , ...)} token, missing comma in token '" - + functionToken + "'.", - SQLError.SQL_STATE_SYNTAX_ERROR); + throw SQLError + .createSQLException( + "Syntax error while processing {fn convert (... , ...)} token, missing comma in token '" + + functionToken + "'.", + SQLError.SQL_STATE_SYNTAX_ERROR, conn.getExceptionInterceptor()); } int indexOfCloseParen = functionToken.indexOf(')', indexOfComma); if (indexOfCloseParen == -1) { - throw SQLError.createSQLException( - "Syntax error while processing {fn convert (... , ...)} token, missing closing parenthesis in token '" - + functionToken + "'.", - SQLError.SQL_STATE_SYNTAX_ERROR); + throw SQLError + .createSQLException( + "Syntax error while processing {fn convert (... , ...)} token, missing closing parenthesis in token '" + + functionToken + "'.", + SQLError.SQL_STATE_SYNTAX_ERROR, conn.getExceptionInterceptor()); } @@ -595,10 +721,10 @@ } if (serverSupportsConvertFn) { - newType = (String) JDBC_CONVERT_TO_MYSQL_TYPE_MAP.get(trimmedType + newType = JDBC_CONVERT_TO_MYSQL_TYPE_MAP.get(trimmedType .toUpperCase(Locale.ENGLISH)); } else { - newType = (String) JDBC_NO_CONVERT_TO_MYSQL_EXPRESSION_MAP + newType = JDBC_NO_CONVERT_TO_MYSQL_EXPRESSION_MAP .get(trimmedType.toUpperCase(Locale.ENGLISH)); // We need a 'special' check here to give a better error message. If @@ -609,18 +735,19 @@ // (date,time,timestamp, datetime) if (newType == null) { - throw SQLError.createSQLException( - "Can't find conversion re-write for type '" - + type - + "' that is applicable for this server version while processing escape tokens.", - SQLError.SQL_STATE_GENERAL_ERROR); + throw SQLError + .createSQLException( + "Can't find conversion re-write for type '" + + type + + "' that is applicable for this server version while processing escape tokens.", + SQLError.SQL_STATE_GENERAL_ERROR, conn.getExceptionInterceptor()); } } if (newType == null) { throw SQLError.createSQLException("Unsupported conversion type '" + type.trim() + "' found while processing escape token.", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, conn.getExceptionInterceptor()); } int replaceIndex = newType.indexOf("?"); @@ -633,16 +760,16 @@ .length())); return convertRewrite.toString(); - } else { + } - StringBuffer castRewrite = new StringBuffer("CAST("); - castRewrite.append(expression); - castRewrite.append(" AS "); - castRewrite.append(newType); - castRewrite.append(")"); + StringBuffer castRewrite = new StringBuffer("CAST("); + castRewrite.append(expression); + castRewrite.append(" AS "); + castRewrite.append(newType); + castRewrite.append(")"); - return castRewrite.toString(); - } + return castRewrite.toString(); + } /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeProcessorResult.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeProcessorResult.java (.../EscapeProcessorResult.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeProcessorResult.java (.../EscapeProcessorResult.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -39,5 +38,5 @@ String escapedSql; - byte usesVariables = Statement.USES_VARIABLES_FALSE; + byte usesVariables = StatementImpl.USES_VARIABLES_FALSE; } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeTokenizer.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeTokenizer.java (.../EscapeTokenizer.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/EscapeTokenizer.java (.../EscapeTokenizer.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -30,49 +29,38 @@ * @author Mark Matthews */ public class EscapeTokenizer { - // ~ Instance fields - // -------------------------------------------------------- + private static final char CHR_ESCAPE = '\\'; + private static final char CHR_SGL_QUOTE = '\''; + private static final char CHR_DBL_QUOTE = '"'; + private static final char CHR_LF = '\n'; + private static final char CHR_CR = '\r'; + private static final char CHR_COMMENT = '-'; + private static final char CHR_BEGIN_TOKEN = '{'; + private static final char CHR_END_TOKEN = '}'; + private static final char CHR_VARIABLE = '@'; - private int bracesLevel = 0; + private String source = null; + private int sourceLength = 0; + private int pos = 0; private boolean emittingEscapeCode = false; - - private boolean inComment = false; - + private boolean sawVariableUse = false; + private int bracesLevel = 0; private boolean inQuotes = false; - - private char lastChar = 0; - - private char lastLastChar = 0; - - private int pos = 0; - private char quoteChar = 0; - private boolean sawVariableUse = false; - - private String source = null; - - private int sourceLength = 0; - - // ~ Constructors - // ----------------------------------------------------------- - /** * Creates a new EscapeTokenizer object. * - * @param s + * @param source * the string to tokenize */ - public EscapeTokenizer(String s) { - this.source = s; - this.sourceLength = s.length(); + public EscapeTokenizer(String source) { + this.source = source; + this.sourceLength = source.length(); this.pos = 0; } - // ~ Methods - // ---------------------------------------------------------------- - /** * Does this tokenizer have more tokens available? * @@ -89,105 +77,109 @@ */ public synchronized String nextToken() { StringBuffer tokenBuf = new StringBuffer(); + boolean backslashEscape = false; if (this.emittingEscapeCode) { - tokenBuf.append("{"); //$NON-NLS-1$ + // Previous token ended at the beginning of an escape code, so this token must start with '{' + tokenBuf.append("{"); this.emittingEscapeCode = false; } for (; this.pos < this.sourceLength; this.pos++) { char c = this.source.charAt(this.pos); - // Detect variable usage - - if (!this.inQuotes && c == '@') { - this.sawVariableUse = true; + // process escape char: (\) + if (c == CHR_ESCAPE) { + tokenBuf.append(c); + backslashEscape = !backslashEscape; + continue; } - if (c == '\'' || c == '"') { - if (this.inQuotes && c == quoteChar) { - if (this.pos + 1 < this.sourceLength) { - if (this.source.charAt(this.pos + 1) == quoteChar) { - // Doubled-up quote escape - tokenBuf.append(quoteChar); - tokenBuf.append(quoteChar); - this.pos++; - continue; - } - } - } - if (this.lastChar != '\\') { - if (this.inQuotes) { - if (this.quoteChar == c) { + // process quotes: ('|") + if ((c == CHR_SGL_QUOTE || c == CHR_DBL_QUOTE) && !backslashEscape) { + tokenBuf.append(c); + if (this.inQuotes) { + if (c == this.quoteChar) { + // look ahead for doubled quote + if ((this.pos + 1 < this.sourceLength) && (this.source.charAt(this.pos + 1) == this.quoteChar)) { + tokenBuf.append(c); + this.pos++; // consume following char '\'' or '"' + } else { this.inQuotes = false; } - } else { - this.inQuotes = true; - this.quoteChar = c; } - } else if (this.lastLastChar == '\\') { - if (this.inQuotes) { - if (this.quoteChar == c) { - this.inQuotes = false; - } - } else { - this.inQuotes = true; - this.quoteChar = c; - } + } else { + this.inQuotes = true; + this.quoteChar = c; } + continue; + } + // process new line: (\n|\r) + if ((c == CHR_LF) || (c == CHR_CR)) { tokenBuf.append(c); - } else if (c == '-') { - if ((this.lastChar == '-') - && ((this.lastLastChar != '\\') & !this.inQuotes)) { - this.inComment = true; - } + backslashEscape = false; + continue; + } - tokenBuf.append(c); - } else if ((c == '\n') || (c == '\r')) { - this.inComment = false; - - tokenBuf.append(c); - } else if (c == '{') { - if (this.inQuotes || this.inComment) { + if (!this.inQuotes && !backslashEscape) { + // process comments: (--) + if (c == CHR_COMMENT) { tokenBuf.append(c); - } else { - this.bracesLevel++; + // look ahead for double hyphen + if ((this.pos + 1 < this.sourceLength) && (this.source.charAt(this.pos + 1) == CHR_COMMENT)) { + // consume following chars until new line or end of string + while (++this.pos < this.sourceLength && c != CHR_LF && c != CHR_CR) { + c = this.source.charAt(this.pos); + tokenBuf.append(c); + } + this.pos--; + } + continue; + } + // process begin token: ({) + if (c == CHR_BEGIN_TOKEN) { + this.bracesLevel++; if (this.bracesLevel == 1) { - this.pos++; this.emittingEscapeCode = true; - + this.pos++; // consume char '{' before returning return tokenBuf.toString(); } - tokenBuf.append(c); + continue; } - } else if (c == '}') { - tokenBuf.append(c); - if (!this.inQuotes && !this.inComment) { - this.lastChar = c; - + // process end token: (}) + if (c == CHR_END_TOKEN) { + tokenBuf.append(c); this.bracesLevel--; - if (this.bracesLevel == 0) { - this.pos++; - + this.pos++; // consume char '}' before returning return tokenBuf.toString(); } + continue; } - } else { - tokenBuf.append(c); + + // detect variable usage: (@) + if (c == CHR_VARIABLE) { + this.sawVariableUse = true; + } } - this.lastLastChar = this.lastChar; - this.lastChar = c; + tokenBuf.append(c); + backslashEscape = false; } return tokenBuf.toString(); } + /** + * Returns true if a variable reference was found. Note that this information isn't accurate until finishing to + * process all tokens from source String. It also can't be used as per token basis. + * + * @return true if a variable reference was found. + */ boolean sawVariableUse() { return this.sawVariableUse; } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ExceptionInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ExceptionInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ExceptionInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,30 @@ +/* + Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + +public interface ExceptionInterceptor extends Extension { + public abstract SQLException interceptException(SQLException sqlEx, Connection conn); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ExportControlled.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ExportControlled.java (.../ExportControlled.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ExportControlled.java (.../ExportControlled.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,33 +1,59 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.SocketException; +import java.net.URL; +import java.security.KeyFactory; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.sql.SQLException; +import java.util.Properties; +import javax.crypto.Cipher; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import com.mysql.jdbc.util.Base64Decoder; + /** * Holds functionality that falls under export-control regulations. * @@ -37,6 +63,8 @@ * Exp $ */ public class ExportControlled { + private static final String SQL_STATE_BAD_SSL_PARAMS = "08000"; + protected static boolean enabled() { // we may wish to un-static-ify this class // this static method call may be removed entirely by the compiler @@ -57,38 +85,276 @@ * perform the handshake. */ protected static void transformSocketToSSLSocket(MysqlIO mysqlIO) - throws CommunicationsException { - javax.net.ssl.SSLSocketFactory sslFact = (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory - .getDefault(); + throws SQLException { + SocketFactory sslFact = new StandardSSLSocketFactory(getSSLSocketFactoryDefaultOrConfigured(mysqlIO), mysqlIO.socketFactory, mysqlIO.mysqlConnection); try { - mysqlIO.mysqlConnection = sslFact.createSocket( - mysqlIO.mysqlConnection, mysqlIO.host, mysqlIO.port, true); + mysqlIO.mysqlConnection = sslFact.connect(mysqlIO.host, mysqlIO.port, null); // need to force TLSv1, or else JSSE tries to do a SSLv2 handshake // which MySQL doesn't understand - ((javax.net.ssl.SSLSocket) mysqlIO.mysqlConnection) - .setEnabledProtocols(new String[] { "TLSv1" }); //$NON-NLS-1$ - ((javax.net.ssl.SSLSocket) mysqlIO.mysqlConnection) - .startHandshake(); + ((SSLSocket) mysqlIO.mysqlConnection).setEnabledProtocols(new String[] { "TLSv1" }); + ((SSLSocket) mysqlIO.mysqlConnection).startHandshake(); if (mysqlIO.connection.getUseUnbufferedInput()) { mysqlIO.mysqlInput = mysqlIO.mysqlConnection.getInputStream(); } else { - mysqlIO.mysqlInput = new BufferedInputStream( - mysqlIO.mysqlConnection.getInputStream(), 16384); + mysqlIO.mysqlInput = new BufferedInputStream(mysqlIO.mysqlConnection.getInputStream(), 16384); } - mysqlIO.mysqlOutput = new BufferedOutputStream( - mysqlIO.mysqlConnection.getOutputStream(), 16384); + mysqlIO.mysqlOutput = new BufferedOutputStream(mysqlIO.mysqlConnection.getOutputStream(), 16384); mysqlIO.mysqlOutput.flush(); + + mysqlIO.socketFactory = sslFact; + } catch (IOException ioEx) { - throw new CommunicationsException(mysqlIO.connection, - mysqlIO.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(mysqlIO.connection, + mysqlIO.getLastPacketSentTimeMs(), mysqlIO.getLastPacketReceivedTimeMs(), + ioEx, mysqlIO.getExceptionInterceptor()); } } + /** + * Implementation of internal socket factory to wrap the SSL socket. + */ + public static class StandardSSLSocketFactory implements SocketFactory { + private SSLSocket rawSocket = null; + private final SSLSocketFactory sslFact; + private final SocketFactory existingSocketFactory; + private final Socket existingSocket; + + public StandardSSLSocketFactory(SSLSocketFactory sslFact, SocketFactory existingSocketFactory, Socket existingSocket) { + this.sslFact = sslFact; + this.existingSocketFactory = existingSocketFactory; + this.existingSocket = existingSocket; + } + public Socket afterHandshake() throws SocketException, IOException { + this.existingSocketFactory.afterHandshake(); + return this.rawSocket; + } + + public Socket beforeHandshake() throws SocketException, IOException { + return this.rawSocket; + } + + public Socket connect(String host, int portNumber, Properties props) throws SocketException, IOException { + this.rawSocket = (SSLSocket) sslFact.createSocket(this.existingSocket, host, portNumber, true); + return this.rawSocket; + } + + } + private ExportControlled() { /* prevent instantiation */ } + + private static SSLSocketFactory getSSLSocketFactoryDefaultOrConfigured( + MysqlIO mysqlIO) throws SQLException { + String clientCertificateKeyStoreUrl = mysqlIO.connection + .getClientCertificateKeyStoreUrl(); + String trustCertificateKeyStoreUrl = mysqlIO.connection + .getTrustCertificateKeyStoreUrl(); + String clientCertificateKeyStoreType = mysqlIO.connection + .getClientCertificateKeyStoreType(); + String clientCertificateKeyStorePassword = mysqlIO.connection + .getClientCertificateKeyStorePassword(); + String trustCertificateKeyStoreType = mysqlIO.connection + .getTrustCertificateKeyStoreType(); + String trustCertificateKeyStorePassword = mysqlIO.connection + .getTrustCertificateKeyStorePassword(); + + if (StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl) + && StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) { + if (mysqlIO.connection.getVerifyServerCertificate()) { + return (SSLSocketFactory) SSLSocketFactory + .getDefault(); + } + } + + TrustManagerFactory tmf = null; + KeyManagerFactory kmf = null; + + try { + tmf = TrustManagerFactory.getInstance(TrustManagerFactory + .getDefaultAlgorithm()); + kmf = KeyManagerFactory.getInstance(KeyManagerFactory + .getDefaultAlgorithm()); + } catch (NoSuchAlgorithmException nsae) { + throw SQLError + .createSQLException( + "Default algorithm definitions for TrustManager and/or KeyManager are invalid. Check java security properties file.", + SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } + + if (!StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)) { + InputStream ksIS = null; + try { + if (!StringUtils.isNullOrEmpty(clientCertificateKeyStoreType)) { + KeyStore clientKeyStore = KeyStore + .getInstance(clientCertificateKeyStoreType); + URL ksURL = new URL(clientCertificateKeyStoreUrl); + char[] password = (clientCertificateKeyStorePassword == null) ? new char[0] + : clientCertificateKeyStorePassword.toCharArray(); + ksIS = ksURL.openStream(); + clientKeyStore.load(ksIS, password); + kmf.init(clientKeyStore, password); + } + } catch (UnrecoverableKeyException uke) { + throw SQLError + .createSQLException( + "Could not recover keys from client keystore. Check password?", + SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (NoSuchAlgorithmException nsae) { + throw SQLError.createSQLException( + "Unsupported keystore algorithm [" + nsae.getMessage() + + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (KeyStoreException kse) { + throw SQLError.createSQLException( + "Could not create KeyStore instance [" + + kse.getMessage() + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (CertificateException nsae) { + throw SQLError.createSQLException("Could not load client" + + clientCertificateKeyStoreType + " keystore from " + + clientCertificateKeyStoreUrl, mysqlIO.getExceptionInterceptor()); + } catch (MalformedURLException mue) { + throw SQLError.createSQLException(clientCertificateKeyStoreUrl + + " does not appear to be a valid URL.", SQL_STATE_BAD_SSL_PARAMS, 0, + false, mysqlIO.getExceptionInterceptor()); + } catch (IOException ioe) { + SQLException sqlEx = SQLError.createSQLException("Cannot open " + + clientCertificateKeyStoreUrl + " [" + + ioe.getMessage() + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + sqlEx.initCause(ioe); + + throw sqlEx; + } finally { + if (ksIS != null) { + try { + ksIS.close(); + } catch (IOException e) { + // can't close input stream, but keystore can be properly initialized + // so we shouldn't throw this exception + } + } + } + } + + if (!StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) { + + InputStream ksIS = null; + try { + if (!StringUtils.isNullOrEmpty(trustCertificateKeyStoreType)) { + KeyStore trustKeyStore = KeyStore + .getInstance(trustCertificateKeyStoreType); + URL ksURL = new URL(trustCertificateKeyStoreUrl); + + char[] password = (trustCertificateKeyStorePassword == null) ? new char[0] + : trustCertificateKeyStorePassword.toCharArray(); + ksIS = ksURL.openStream(); + trustKeyStore.load(ksIS, password); + tmf.init(trustKeyStore); + } + } catch (NoSuchAlgorithmException nsae) { + throw SQLError.createSQLException( + "Unsupported keystore algorithm [" + nsae.getMessage() + + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (KeyStoreException kse) { + throw SQLError.createSQLException( + "Could not create KeyStore instance [" + + kse.getMessage() + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (CertificateException nsae) { + throw SQLError.createSQLException("Could not load trust" + + trustCertificateKeyStoreType + " keystore from " + + trustCertificateKeyStoreUrl, SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (MalformedURLException mue) { + throw SQLError.createSQLException(trustCertificateKeyStoreUrl + + " does not appear to be a valid URL.", SQL_STATE_BAD_SSL_PARAMS, 0, + false, mysqlIO.getExceptionInterceptor()); + } catch (IOException ioe) { + SQLException sqlEx = SQLError.createSQLException("Cannot open " + + trustCertificateKeyStoreUrl + " [" + ioe.getMessage() + + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + + sqlEx.initCause(ioe); + + throw sqlEx; + } finally { + if (ksIS != null) { + try { + ksIS.close(); + } catch (IOException e) { + // can't close input stream, but keystore can be properly initialized + // so we shouldn't throw this exception + } + } + } + } + + SSLContext sslContext = null; + + try { + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl) ? null : kmf.getKeyManagers(), mysqlIO.connection + .getVerifyServerCertificate() ? tmf.getTrustManagers() + : new X509TrustManager[] { new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] chain, + String authType) { + // return without complaint + } + + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + // return without complaint + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } }, null); + + return sslContext.getSocketFactory(); + } catch (NoSuchAlgorithmException nsae) { + throw SQLError.createSQLException("TLS" + + " is not a valid SSL protocol.", + SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } catch (KeyManagementException kme) { + throw SQLError.createSQLException("KeyManagementException: " + + kme.getMessage(), SQL_STATE_BAD_SSL_PARAMS, 0, false, mysqlIO.getExceptionInterceptor()); + } + } + + public static boolean isSSLEstablished(MysqlIO mysqlIO) { + return SSLSocket.class.isAssignableFrom(mysqlIO.mysqlConnection.getClass()); + } + + public static RSAPublicKey decodeRSAPublicKey(String key, ExceptionInterceptor interceptor) throws SQLException { + + try { + if (key == null) throw new SQLException("key parameter is null"); + + int offset = key.indexOf("\n")+1; + int len = key.indexOf("-----END PUBLIC KEY-----") - offset; + + // TODO: use standard decoders with Java 6+ + byte[] certificateData = Base64Decoder.decode(key.getBytes(), offset, len); + + X509EncodedKeySpec spec = new X509EncodedKeySpec(certificateData); + KeyFactory kf = KeyFactory.getInstance("RSA"); + return (RSAPublicKey) kf.generatePublic(spec); + } catch (Exception ex) { + throw SQLError.createSQLException("Unable to decode public key", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, ex, interceptor); + } + } + + public static byte[] encryptWithRSAPublicKey(byte[] source, RSAPublicKey key, ExceptionInterceptor interceptor) throws SQLException { + try { + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, key); + return cipher.doFinal(source); + } catch (Exception ex) { + throw SQLError.createSQLException(ex.getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, ex, interceptor); + } + } + + } \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Extension.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Extension.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Extension.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,56 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +public interface Extension { + + /** + * Called once per connection that wants to use the extension + * + * The properties are the same ones passed in in the URL or arguments to + * Driver.connect() or DriverManager.getConnection(). + * + * @param conn the connection for which this extension is being created + * @param props configuration values as passed to the connection. Note that + * in order to support javax.sql.DataSources, configuration properties specific + * to an interceptor must be passed via setURL() on the + * DataSource. Extension properties are not exposed via + * accessor/mutator methods on DataSources. + * + * @throws SQLException should be thrown if the the Extension + * can not initialize itself. + */ + + public abstract void init(Connection conn, Properties props) throws SQLException; + + /** + * Called by the driver when this extension should release any resources + * it is holding and cleanup internally before the connection is + * closed. + */ + public abstract void destroy(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/FailoverConnectionProxy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/FailoverConnectionProxy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/FailoverConnectionProxy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,228 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +public class FailoverConnectionProxy extends LoadBalancingConnectionProxy { + class FailoverInvocationHandler extends + ConnectionErrorFiringInvocationHandler { + + public FailoverInvocationHandler(Object toInvokeOn) { + super(toInvokeOn); + } + + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + String methodName = method.getName(); + + if (failedOver && methodName.indexOf("execute") != -1) { + queriesIssuedFailedOver++; + } + + return super.invoke(proxy, method, args); + } + + } + + boolean failedOver; + boolean hasTriedMaster; + private long masterFailTimeMillis; + boolean preferSlaveDuringFailover; + private String primaryHostPortSpec; + private long queriesBeforeRetryMaster; + long queriesIssuedFailedOver; + private int secondsBeforeRetryMaster; + + FailoverConnectionProxy(List hosts, Properties props) throws SQLException { + super(hosts, props); + ConnectionPropertiesImpl connectionProps = new ConnectionPropertiesImpl(); + connectionProps.initializeProperties(props); + + this.queriesBeforeRetryMaster = connectionProps.getQueriesBeforeRetryMaster(); + this.secondsBeforeRetryMaster = connectionProps.getSecondsBeforeRetryMaster(); + this.preferSlaveDuringFailover = false; + } + + protected ConnectionErrorFiringInvocationHandler createConnectionProxy( + Object toProxy) { + return new FailoverInvocationHandler(toProxy); + } + + // slightly different behavior than load balancing, we only pick a new + // connection if we've issued enough queries or enough time has passed + // since we failed over, and that's all handled in pickNewConnection(). + synchronized void dealWithInvocationException(InvocationTargetException e) + throws SQLException, Throwable, InvocationTargetException { + Throwable t = e.getTargetException(); + + if (t != null) { + if (failedOver) { // try and fall back + createPrimaryConnection(); + + if (this.currentConn != null) { + throw t; + } + } + + failOver(); + + throw t; + } + + throw e; + } + + public synchronized Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + String methodName = method.getName(); + + if ("setPreferSlaveDuringFailover".equals(methodName)) { + preferSlaveDuringFailover = ((Boolean) args[0]).booleanValue(); + } else if ("clearHasTriedMaster".equals(methodName)) { + hasTriedMaster = false; + } else if ("hasTriedMaster".equals(methodName)) { + return Boolean.valueOf(hasTriedMaster); + } else if ("isMasterConnection".equals(methodName)) { + return Boolean.valueOf(!failedOver); + } else if ("isSlaveConnection".equals(methodName)) { + return Boolean.valueOf(failedOver); + } else if ("setReadOnly".equals(methodName)) { + if (failedOver) { + return null; // no-op when failed over + } + } else if ("setAutoCommit".equals(methodName) && failedOver && + shouldFallBack() && Boolean.TRUE.equals(args[0]) && failedOver) { + createPrimaryConnection(); + + return super.invoke(proxy, method, args, failedOver); + } else if ("hashCode".equals(methodName)) { + return Integer.valueOf(this.hashCode()); + } else if ("equals".equals(methodName)) { + if (args[0] instanceof Proxy) { + return Boolean.valueOf((((Proxy) args[0]).equals(this))); + } + return Boolean.valueOf(this.equals(args[0])); + } + return super.invoke(proxy, method, args, failedOver); + } + + private synchronized void createPrimaryConnection() throws SQLException { + try { + this.currentConn = createConnectionForHost(this.primaryHostPortSpec); + this.failedOver = false; + this.hasTriedMaster = true; + + // reset failed-over state + this.queriesIssuedFailedOver = 0; + } catch (SQLException sqlEx) { + this.failedOver = true; + + if (this.currentConn != null) { + this.currentConn.getLog().logWarn("Connection to primary host failed", sqlEx); + } + } + } + + synchronized void invalidateCurrentConnection() throws SQLException { + if (!this.failedOver) { + this.failedOver = true; + this.queriesIssuedFailedOver = 0; + this.masterFailTimeMillis = System.currentTimeMillis(); + } + super.invalidateCurrentConnection(); + } + + protected synchronized void pickNewConnection() throws SQLException { + if (this.isClosed && this.closedExplicitly) { + return; + } + + if (this.primaryHostPortSpec == null) { + this.primaryHostPortSpec = this.hostList.remove(0); // first connect + } + + if (this.currentConn == null || (this.failedOver && shouldFallBack())) { + createPrimaryConnection(); + + if (this.currentConn != null) { + return; + } + } + + failOver(); + } + + private synchronized void failOver() throws SQLException { + if (failedOver) { + Iterator> iter = liveConnections.entrySet().iterator(); + + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + entry.getValue().close(); + } + + liveConnections.clear(); + } + + super.pickNewConnection(); + + if (this.currentConn.getFailOverReadOnly()) { + this.currentConn.setReadOnly(true); + } else { + this.currentConn.setReadOnly(false); + } + + this.failedOver = true; + } + + /** + * Should we try to connect back to the master? We try when we've been + * failed over >= this.secondsBeforeRetryMaster _or_ we've issued > + * this.queriesIssuedFailedOver + * + * @return DOCUMENT ME! + */ + private boolean shouldFallBack() { + long secondsSinceFailedOver = (System.currentTimeMillis() - this.masterFailTimeMillis) / 1000; + + if (secondsSinceFailedOver >= this.secondsBeforeRetryMaster) { + // reset the timer + this.masterFailTimeMillis = System.currentTimeMillis(); + + return true; + } else if (this.queriesBeforeRetryMaster != 0 && this.queriesIssuedFailedOver >= this.queriesBeforeRetryMaster) { + return true; + } + + return false; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Field.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Field.java (.../Field.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Field.java (.../Field.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,32 +1,32 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.UnsupportedEncodingException; import java.sql.SQLException; import java.sql.Types; +import java.util.regex.PatternSyntaxException; /** * Field is a class used to describe fields in a ResultSet @@ -52,7 +52,7 @@ private String collationName = null; - private Connection connection = null; + private MySQLConnection connection = null; private String databaseName = null; @@ -61,10 +61,10 @@ // database name info private int databaseNameStart = -1; - private int defaultValueLength = -1; + protected int defaultValueLength = -1; // default value info - from COM_LIST_FIELDS execution - private int defaultValueStart = -1; + protected int defaultValueStart = -1; private String fullName = null; @@ -111,11 +111,13 @@ private boolean isSingleBit; private int maxBytesPerChar; + + private final boolean valueNeedsQuoting; /** * Constructor used when communicating with 4.1 and newer servers */ - Field(Connection conn, byte[] buffer, int databaseNameStart, + Field(MySQLConnection conn, byte[] buffer, int databaseNameStart, int databaseNameLength, int tableNameStart, int tableNameLength, int originalTableNameStart, int originalTableNameLength, int nameStart, int nameLength, int originalColumnNameStart, @@ -156,18 +158,22 @@ checkForImplicitTemporaryTable(); // Re-map to 'real' blob type, if we're a BLOB - + boolean isFromFunction = this.originalTableNameLength == 0; + if (this.mysqlType == MysqlDefs.FIELD_TYPE_BLOB) { - boolean isFromFunction = this.originalTableNameLength == 0; - if (this.connection != null && this.connection.getBlobsAreStrings() || (this.connection.getFunctionsNeverReturnBlobs() && isFromFunction)) { this.sqlType = Types.VARCHAR; this.mysqlType = MysqlDefs.FIELD_TYPE_VARCHAR; } else if (this.charsetIndex == 63 || !this.connection.versionMeetsMinimum(4, 1, 0)) { - setBlobTypeBasedOnLength(); - this.sqlType = MysqlDefs.mysqlToJavaType(this.mysqlType); + if (this.connection.getUseBlobToStoreUTF8OutsideBMP() + && shouldSetupForUtf8StringInBlob()) { + setupForUtf8StringInBlob(); + } else { + setBlobTypeBasedOnLength(); + this.sqlType = MysqlDefs.mysqlToJavaType(this.mysqlType); + } } else { // *TEXT masquerading as blob this.mysqlType = MysqlDefs.FIELD_TYPE_VAR_STRING; @@ -192,6 +198,12 @@ this.charsetName = this.connection .getCharsetNameForIndex(this.charsetIndex); + // ucs2, utf16, and utf32 cannot be used as a client character set, + // but if it was received from server under some circumstances + // we can parse them as utf16 + if ("UnicodeBig".equals(this.charsetName)) { + this.charsetName = "UTF-16"; + } // Handle VARBINARY/BINARY (server doesn't have a different type // for this @@ -202,9 +214,12 @@ this.mysqlType == MysqlDefs.FIELD_TYPE_VAR_STRING && isBinary && this.charsetIndex == 63) { - if (this.isOpaqueBinary()) { + if (this.connection != null && (this.connection.getFunctionsNeverReturnBlobs() && isFromFunction)) { + this.sqlType = Types.VARCHAR; + this.mysqlType = MysqlDefs.FIELD_TYPE_VARCHAR; + } else if (this.isOpaqueBinary()) { this.sqlType = Types.VARBINARY; - } + } } if (this.connection.versionMeetsMinimum(4, 1, 0) && @@ -279,12 +294,74 @@ break; } } + this.valueNeedsQuoting = determineNeedsQuoting(); } + private boolean shouldSetupForUtf8StringInBlob() throws SQLException { + String includePattern = this.connection + .getUtf8OutsideBmpIncludedColumnNamePattern(); + String excludePattern = this.connection + .getUtf8OutsideBmpExcludedColumnNamePattern(); + + if (excludePattern != null + && !StringUtils.isEmptyOrWhitespaceOnly(excludePattern)) { + try { + if (getOriginalName().matches(excludePattern)) { + if (includePattern != null + && !StringUtils.isEmptyOrWhitespaceOnly(includePattern)) { + try { + if (getOriginalName().matches(includePattern)) { + return true; + } + } catch (PatternSyntaxException pse) { + SQLException sqlEx = SQLError + .createSQLException( + "Illegal regex specified for \"utf8OutsideBmpIncludedColumnNamePattern\"", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.connection.getExceptionInterceptor()); + + if (!this.connection.getParanoid()) { + sqlEx.initCause(pse); + } + + throw sqlEx; + } + } + + return false; + } + } catch (PatternSyntaxException pse) { + SQLException sqlEx = SQLError + .createSQLException( + "Illegal regex specified for \"utf8OutsideBmpExcludedColumnNamePattern\"", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.connection.getExceptionInterceptor()); + + if (!this.connection.getParanoid()) { + sqlEx.initCause(pse); + } + + throw sqlEx; + } + } + + return true; + } + + private void setupForUtf8StringInBlob() { + if (this.length == MysqlDefs.LENGTH_TINYBLOB || this.length == MysqlDefs.LENGTH_BLOB) { + this.mysqlType = MysqlDefs.FIELD_TYPE_VARCHAR; + this.sqlType = Types.VARCHAR; + } else { + this.mysqlType = MysqlDefs.FIELD_TYPE_VAR_STRING; + this.sqlType = Types.LONGVARCHAR; + } + + this.charsetIndex = 33; + } + /** * Constructor used when communicating with pre 4.1 servers */ - Field(Connection conn, byte[] buffer, int nameStart, int nameLength, + Field(MySQLConnection conn, byte[] buffer, int nameStart, int nameLength, int tableNameStart, int tableNameLength, int length, int mysqlType, short colFlag, int colDecimals) throws SQLException { this(conn, buffer, -1, -1, tableNameStart, tableNameLength, -1, -1, @@ -302,8 +379,45 @@ this.sqlType = jdbcType; this.colFlag = 0; this.colDecimals = 0; + this.valueNeedsQuoting = determineNeedsQuoting(); } - + + /** + * Used by prepared statements to re-use result set data conversion methods + * when generating bound parmeter retrieval instance for statement + * interceptors. + * + * @param tableName + * not used + * @param columnName + * not used + * @param charsetIndex + * the MySQL collation/character set index + * @param jdbcType + * from java.sql.Types + * @param length + * length in characters or bytes (for BINARY data). + */ + Field(String tableName, String columnName, int charsetIndex, int jdbcType, + int length) { + this.tableName = tableName; + this.name = columnName; + this.length = length; + this.sqlType = jdbcType; + this.colFlag = 0; + this.colDecimals = 0; + this.charsetIndex = charsetIndex; + this.valueNeedsQuoting = determineNeedsQuoting(); + + switch (this.sqlType) { + case Types.BINARY: + case Types.VARBINARY: + this.colFlag |= 128; + this.colFlag |= 16; + break; + } + } + private void checkForImplicitTemporaryTable() { this.isImplicitTempTable = this.tableNameLength > 5 && this.buffer[tableNameStart] == (byte) '#' @@ -322,6 +436,18 @@ return this.charsetName; } + public void setCharacterSet(String javaEncodingName) throws SQLException { + this.charsetName = javaEncodingName; + try { + this.charsetIndex = CharsetMapping + .getCharsetIndexForMysqlEncodingName(javaEncodingName); + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + } + public synchronized String getCollation() throws SQLException { if (this.collationName == null) { if (this.connection != null) { @@ -387,15 +513,21 @@ } } } else { - this.collationName = CharsetMapping.INDEX_TO_COLLATION[charsetIndex]; + try { + this.collationName = CharsetMapping.INDEX_TO_COLLATION[charsetIndex]; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } } } } } return this.collationName; } - + public String getColumnLabel() throws SQLException { return getName(); // column name if not aliased, alias if used } @@ -479,9 +611,8 @@ public synchronized int getMaxBytesPerCharacter() throws SQLException { if (this.maxBytesPerChar == 0) { - this.maxBytesPerChar = this.connection.getMaxBytesPerChar(getCharacterSet()); + this.maxBytesPerChar = this.connection.getMaxBytesPerChar(this.charsetIndex, getCharacterSet()); } - return this.maxBytesPerChar; } @@ -606,17 +737,8 @@ stringStart, stringLength); } else { // we have no converter, use JVM converter - byte[] stringBytes = new byte[stringLength]; - - int endIndex = stringStart + stringLength; - int pos = 0; - - for (int i = stringStart; i < endIndex; i++) { - stringBytes[pos++] = this.buffer[i]; - } - try { - stringVal = new String(stringBytes, encoding); + stringVal = StringUtils.toString(buffer, stringStart, stringLength, encoding); } catch (UnsupportedEncodingException ue) { throw new RuntimeException(Messages .getString("Field.12") + encoding //$NON-NLS-1$ @@ -794,6 +916,10 @@ return ((this.colFlag & 32) > 0); } + public void setUnsigned() { + this.colFlag |= 32; + } + /** * DOCUMENT ME! * @@ -841,10 +967,12 @@ * @param conn * DOCUMENT ME! */ - public void setConnection(Connection conn) { + public void setConnection(MySQLConnection conn) { this.connection = conn; - this.charsetName = this.connection.getEncoding(); + if (this.charsetName == null || this.charsetIndex == 0) { + this.charsetName = this.connection.getEncoding(); + } } void setMysqlType(int type) { @@ -858,31 +986,72 @@ public String toString() { try { - StringBuffer asString = new StringBuffer(128); + StringBuffer asString = new StringBuffer(); asString.append(super.toString()); - - asString.append("\n catalog: "); + asString.append("["); + asString.append("catalog="); asString.append(this.getDatabaseName()); - asString.append("\n table name: "); + asString.append(",tableName="); asString.append(this.getTableName()); - asString.append("\n original table name: "); + asString.append(",originalTableName="); asString.append(this.getOriginalTableName()); - asString.append("\n column name: "); + asString.append(",columnName="); asString.append(this.getName()); - asString.append("\n original column name: "); + asString.append(",originalColumnName="); asString.append(this.getOriginalName()); - asString.append("\n MySQL data type: "); + asString.append(",mysqlType="); asString.append(getMysqlType()); asString.append("("); asString.append(MysqlDefs.typeToName(getMysqlType())); asString.append(")"); - - if (this.buffer != null) { - asString.append("\n\nData as received from server:\n\n"); - asString.append(StringUtils.dumpAsHex(this.buffer, - this.buffer.length)); + asString.append(",flags="); + + if (isAutoIncrement()) { + asString.append(" AUTO_INCREMENT"); } + + if (isPrimaryKey()) { + asString.append(" PRIMARY_KEY"); + } + + if (isUniqueKey()) { + asString.append(" UNIQUE_KEY"); + } + + if (isBinary()) { + asString.append(" BINARY"); + } + + if (isBlob()) { + asString.append(" BLOB"); + } + + if (isMultipleKey()) { + asString.append(" MULTI_KEY"); + } + + if (isUnsigned()) { + asString.append(" UNSIGNED"); + } + + if (isZeroFill()) { + asString.append(" ZEROFILL"); + } + asString.append(", charsetIndex="); + asString.append(this.charsetIndex); + asString.append(", charsetName="); + asString.append(this.charsetName); + + + //if (this.buffer != null) { + // asString.append("\n\nData as received from server:\n\n"); + // asString.append(StringUtils.dumpAsHex(this.buffer, + // this.buffer.length)); + //} + + asString.append("]"); + return asString.toString(); } catch (Throwable t) { return super.toString(); @@ -892,4 +1061,31 @@ protected boolean isSingleBit() { return this.isSingleBit; } + + protected boolean getvalueNeedsQuoting() { + return this.valueNeedsQuoting; + } + + private boolean determineNeedsQuoting() { + boolean retVal = false; + + switch (this.sqlType) { + case Types.BIGINT: + case Types.BIT: + case Types.DECIMAL: + case Types.DOUBLE: + case Types.FLOAT: + case Types.INTEGER: + case Types.NUMERIC: + case Types.REAL: + case Types.SMALLINT: + case Types.TINYINT: + retVal = false; + break; + default: + retVal = true; + } + return retVal; + + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/IterateBlock.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/IterateBlock.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/IterateBlock.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,75 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Iterator; + +import com.mysql.jdbc.DatabaseMetaData.IteratorWithCleanup; + +public abstract class IterateBlock { + IteratorWithCleanup iteratorWithCleanup; + Iterator javaIterator; + boolean stopIterating = false; + + IterateBlock(IteratorWithCleanup i) { + this.iteratorWithCleanup = i; + this.javaIterator = null; + } + + IterateBlock(Iterator i) { + this.javaIterator = i; + this.iteratorWithCleanup = null; + } + + public void doForAll() throws SQLException { + if (this.iteratorWithCleanup != null) { + try { + while (this.iteratorWithCleanup.hasNext()) { + forEach(this.iteratorWithCleanup.next()); + + if (this.stopIterating) { + break; + } + } + } finally { + this.iteratorWithCleanup.close(); + } + } else { + while (this.javaIterator.hasNext()) { + forEach(this.javaIterator.next()); + + if (this.stopIterating) { + break; + } + } + } + } + + abstract void forEach(T each) throws SQLException; + + public final boolean fullIteration() { + return !this.stopIterating; + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4CallableStatement.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4CallableStatement.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4CallableStatement.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,283 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.SQLException; +import java.sql.RowId; +import java.sql.SQLXML; +import java.sql.NClob; + + + +public class JDBC4CallableStatement extends CallableStatement { + + public JDBC4CallableStatement(MySQLConnection conn, + CallableStatementParamInfo paramInfo) throws SQLException { + super(conn, paramInfo); + } + + public JDBC4CallableStatement(MySQLConnection conn, String sql, + String catalog, boolean isFunctionCall) throws SQLException { + super(conn, sql, catalog, isFunctionCall); + } + + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + JDBC4PreparedStatementHelper.setRowId(this, parameterIndex, x); + } + + public void setRowId(String parameterName, RowId x) throws SQLException { + JDBC4PreparedStatementHelper.setRowId(this, getNamedParamIndex( + parameterName, false), x); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + JDBC4PreparedStatementHelper.setSQLXML(this, parameterIndex, xmlObject); + } + + public void setSQLXML(String parameterName, SQLXML xmlObject) + throws SQLException { + JDBC4PreparedStatementHelper.setSQLXML(this, getNamedParamIndex( + parameterName, false), xmlObject); + + } + + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + SQLXML retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getSQLXML(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + + } + + public SQLXML getSQLXML(String parameterName) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely + // not going to + // be + // from ?= + + SQLXML retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getSQLXML(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + public RowId getRowId(int parameterIndex) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + RowId retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getRowId(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + public RowId getRowId(String parameterName) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely + // not going to + // be + // from ?= + + RowId retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getRowId(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * JDBC 4.0 Set a NCLOB parameter. + * + * @param i + * the first parameter is 1, the second is 2, ... + * @param x + * an object representing a NCLOB + * + * @throws SQLException + * if a database error occurs + */ + public void setNClob(int parameterIndex, NClob value) throws SQLException { + JDBC4PreparedStatementHelper.setNClob(this, parameterIndex, value); + } + + public void setNClob(String parameterName, NClob value) throws SQLException { + JDBC4PreparedStatementHelper.setNClob(this, getNamedParamIndex( + parameterName, false), value); + + } + + public void setNClob(String parameterName, Reader reader) + throws SQLException { + setNClob(getNamedParamIndex(parameterName, false), reader); + + } + + public void setNClob(String parameterName, Reader reader, long length) + throws SQLException { + setNClob(getNamedParamIndex(parameterName, false), reader, length); + + } + + public void setNString(String parameterName, String value) + throws SQLException { + setNString(getNamedParamIndex(parameterName, false), value); + } + + /** + * @see java.sql.CallableStatement#getCharacterStream(int) + */ + public Reader getCharacterStream(int parameterIndex) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Reader retValue = rs + .getCharacterStream(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getCharacterStream(java.lang.String) + */ + public Reader getCharacterStream(String parameterName) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely + // not going to + // be + // from ?= + + Reader retValue = rs + .getCharacterStream(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getNCharacterStream(int) + */ + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + Reader retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getNCharacterStream(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getNCharacterStream(java.lang.String) + */ + public Reader getNCharacterStream(String parameterName) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely + // not going to + // be + // from ?= + + Reader retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getNCharacterStream(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getNClob(int) + */ + public NClob getNClob(int parameterIndex) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + NClob retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getNClob(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getNClob(java.lang.String) + */ + public NClob getNClob(String parameterName) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely + // not going to + // be + // from ?= + + NClob retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getNClob(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getNString(int) + */ + public String getNString(int parameterIndex) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(parameterIndex); + + String retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getNString(mapOutputParameterIndexToRsIndex(parameterIndex)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } + + /** + * @see java.sql.CallableStatement#getNString(java.lang.String) + */ + public String getNString(String parameterName) throws SQLException { + ResultSetInternalMethods rs = getOutputParameters(0); // definitely + // not going to + // be + // from ?= + + String retValue = ((com.mysql.jdbc.JDBC4ResultSet) rs) + .getNString(fixParameterName(parameterName)); + + this.outputParamWasNull = rs.wasNull(); + + return retValue; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ClientInfoProvider.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ClientInfoProvider.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ClientInfoProvider.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,137 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.sql.SQLClientInfoException; +import java.util.Properties; + + + +/** + * Classes that implement this interface and provide a no-args constructor + * can be used by the driver to store and retrieve client information and/or + * labels. + * + * The driver will create an instance for each Connection instance, and call + * initialize() once and only once. When the connection is closed, destroy() + * will be called, and the provider is expected to clean up any resources at + * this time. + * + * @version $Id$ + */ +public interface JDBC4ClientInfoProvider { + /** + * Called once by the driver when it needs to configure the provider. + * + * @param conn the connection that the provider belongs too. + * @param configurationProps a java.util.Properties instance that contains + * configuration information for the connection. + * @throws SQLException if initialization fails. + */ + public void initialize(java.sql.Connection conn, Properties configurationProps) throws SQLException; + + /** + * Called once by the driver when the connection this provider instance + * belongs to is being closed. + * + * Implementations are expected to clean up and resources at this point + * in time. + * + * @throws SQLException if an error occurs. + */ + public void destroy() throws SQLException; + + /** + * Returns the client info for the connection that this provider + * instance belongs to. The connection instance is passed as an argument + * for convenience's sake. + * + * Providers can use the connection to communicate with the database, + * but it will be within the scope of any ongoing transactions, so therefore + * implementations should not attempt to change isolation level, autocommit settings + * or call rollback() or commit() on the connection. + * + * @param conn + * @return + * @throws SQLException + * + * @see java.sql.Connection#getClientInfo() + */ + public Properties getClientInfo(java.sql.Connection conn) throws SQLException; + + /** + * Returns the client info for the connection that this provider + * instance belongs to. The connection instance is passed as an argument + * for convenience's sake. + * + * Providers can use the connection to communicate with the database, + * but it will be within the scope of any ongoing transactions, so therefore + * implementations should not attempt to change isolation level, autocommit settings + * or call rollback() or commit() on the connection. + * + * @param conn + * @return + * @throws SQLException + * + * @see java.sql.Connection#getClientInfo(java.lang.String) + */ + public String getClientInfo(java.sql.Connection conn, String name) throws SQLException; + + /** + * Sets the client info for the connection that this provider + * instance belongs to. The connection instance is passed as an argument + * for convenience's sake. + * + * Providers can use the connection to communicate with the database, + * but it will be within the scope of any ongoing transactions, so therefore + * implementations should not attempt to change isolation level, autocommit settings + * or call rollback() or commit() on the connection. + * + * @param conn + * @return + * @throws SQLException + * + * @see java.sql.Connection#setClientInfo(java.util.Properties) + */ + public void setClientInfo(java.sql.Connection conn, Properties properties) throws SQLClientInfoException; + + /** + * Sets the client info for the connection that this provider + * instance belongs to. The connection instance is passed as an argument + * for convenience's sake. + * + * Providers can use the connection to communicate with the database, + * but it will be within the scope of any ongoing transactions, so therefore + * implementations should not attempt to change isolation level, autocommit settings + * or call rollback() or commit() on the connection. + * + * @param conn + * @return + * @throws SQLException + * + * @see java.sql.Connection#setClientInfo(java.lang.String,java.lang.String) + */ + public void setClientInfo(java.sql.Connection conn, String name, String value) throws SQLClientInfoException; +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ClientInfoProviderSP.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ClientInfoProviderSP.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ClientInfoProviderSP.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,168 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLClientInfoException; +import java.util.Enumeration; +import java.util.Properties; + +public class JDBC4ClientInfoProviderSP implements JDBC4ClientInfoProvider { + PreparedStatement setClientInfoSp; + + PreparedStatement getClientInfoSp; + + PreparedStatement getClientInfoBulkSp; + + public synchronized void initialize(java.sql.Connection conn, + Properties configurationProps) throws SQLException { + String identifierQuote = conn.getMetaData().getIdentifierQuoteString(); + String setClientInfoSpName = configurationProps.getProperty( + "clientInfoSetSPName", "setClientInfo"); + String getClientInfoSpName = configurationProps.getProperty( + "clientInfoGetSPName", "getClientInfo"); + String getClientInfoBulkSpName = configurationProps.getProperty( + "clientInfoGetBulkSPName", "getClientInfoBulk"); + String clientInfoCatalog = configurationProps.getProperty( + "clientInfoCatalog", ""); // "" means use current from + // connection + + String catalog = "".equals(clientInfoCatalog) ? conn.getCatalog() + : clientInfoCatalog; + + this.setClientInfoSp = ((com.mysql.jdbc.Connection) conn) + .clientPrepareStatement("CALL " + identifierQuote + catalog + + identifierQuote + "." + identifierQuote + + setClientInfoSpName + identifierQuote + "(?, ?)"); + + this.getClientInfoSp = ((com.mysql.jdbc.Connection) conn) + .clientPrepareStatement("CALL" + identifierQuote + catalog + + identifierQuote + "." + identifierQuote + + getClientInfoSpName + identifierQuote + "(?)"); + + this.getClientInfoBulkSp = ((com.mysql.jdbc.Connection) conn) + .clientPrepareStatement("CALL " + identifierQuote + catalog + + identifierQuote + "." + identifierQuote + + getClientInfoBulkSpName + identifierQuote + "()"); + } + + public synchronized void destroy() throws SQLException { + if (this.setClientInfoSp != null) { + this.setClientInfoSp.close(); + this.setClientInfoSp = null; + } + + if (this.getClientInfoSp != null) { + this.getClientInfoSp.close(); + this.getClientInfoSp = null; + } + + if (this.getClientInfoBulkSp != null) { + this.getClientInfoBulkSp.close(); + this.getClientInfoBulkSp = null; + } + } + + public synchronized Properties getClientInfo(java.sql.Connection conn) + throws SQLException { + ResultSet rs = null; + + Properties props = new Properties(); + + try { + this.getClientInfoBulkSp.execute(); + + rs = this.getClientInfoBulkSp.getResultSet(); + + while (rs.next()) { + props.setProperty(rs.getString(1), rs.getString(2)); + } + } finally { + if (rs != null) { + rs.close(); + } + } + + return props; + } + + public synchronized String getClientInfo(java.sql.Connection conn, + String name) throws SQLException { + ResultSet rs = null; + + String clientInfo = null; + + try { + this.getClientInfoSp.setString(1, name); + this.getClientInfoSp.execute(); + + rs = this.getClientInfoSp.getResultSet(); + + if (rs.next()) { + clientInfo = rs.getString(1); + } + } finally { + if (rs != null) { + rs.close(); + } + } + + return clientInfo; + } + + public synchronized void setClientInfo(java.sql.Connection conn, + Properties properties) throws SQLClientInfoException { + try { + Enumeration propNames = properties.propertyNames(); + + while (propNames.hasMoreElements()) { + String name = (String) propNames.nextElement(); + String value = properties.getProperty(name); + + setClientInfo(conn, name, value); + } + } catch (SQLException sqlEx) { + SQLClientInfoException clientInfoEx = new SQLClientInfoException(); + clientInfoEx.initCause(sqlEx); + + throw clientInfoEx; + } + } + + public synchronized void setClientInfo(java.sql.Connection conn, + String name, String value) throws SQLClientInfoException { + try { + this.setClientInfoSp.setString(1, name); + this.setClientInfoSp.setString(2, value); + this.setClientInfoSp.execute(); + } catch (SQLException sqlEx) { + SQLClientInfoException clientInfoEx = new SQLClientInfoException(); + clientInfoEx.initCause(sqlEx); + + throw clientInfoEx; + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4CommentClientInfoProvider.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4CommentClientInfoProvider.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4CommentClientInfoProvider.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,107 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLClientInfoException; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +/** + * An implementation of JDBC4ClientInfoProvider that exposes + * the client info as a comment prepended to all statements issued + * by the driver. + * + * Client information is never read from the server with this + * implementation, it is always cached locally. + * + * @version $Id$ + */ + +public class JDBC4CommentClientInfoProvider implements JDBC4ClientInfoProvider { + private Properties clientInfo; + + public synchronized void initialize(java.sql.Connection conn, + Properties configurationProps) throws SQLException { + this.clientInfo = new Properties(); + } + + public synchronized void destroy() throws SQLException { + this.clientInfo = null; + } + + public synchronized Properties getClientInfo(java.sql.Connection conn) + throws SQLException { + return this.clientInfo; + } + + public synchronized String getClientInfo(java.sql.Connection conn, + String name) throws SQLException { + return this.clientInfo.getProperty(name); + } + + public synchronized void setClientInfo(java.sql.Connection conn, + Properties properties) throws SQLClientInfoException { + this.clientInfo = new Properties(); + + Enumeration propNames = properties.propertyNames(); + + while (propNames.hasMoreElements()) { + String name = (String)propNames.nextElement(); + + this.clientInfo.put(name, properties.getProperty(name)); + } + + setComment(conn); + } + + public synchronized void setClientInfo(java.sql.Connection conn, + String name, String value) throws SQLClientInfoException { + this.clientInfo.setProperty(name, value); + setComment(conn); + } + + private synchronized void setComment(java.sql.Connection conn) { + StringBuffer commentBuf = new StringBuffer(); + Iterator elements = this.clientInfo.entrySet().iterator(); + + while (elements.hasNext()) { + if (commentBuf.length() > 0) { + commentBuf.append(", "); + } + + Map.Entry entry = (Map.Entry)elements.next(); + commentBuf.append("" + entry.getKey()); + commentBuf.append("="); + commentBuf.append("" + entry.getValue()); + } + + ((com.mysql.jdbc.Connection)conn).setStatementComment( + commentBuf.toString()); + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4Connection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4Connection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4Connection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,240 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.Blob; +import java.sql.Clob; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.NClob; +import java.sql.Struct; +import java.util.Properties; +import java.util.TimerTask; + + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.Messages; +import com.mysql.jdbc.SQLError; + + +public class JDBC4Connection extends ConnectionImpl { + private JDBC4ClientInfoProvider infoProvider; + + public JDBC4Connection(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException { + super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url); + // TODO Auto-generated constructor stub + } + + public SQLXML createSQLXML() throws SQLException { + return new JDBC4MysqlSQLXML(getExceptionInterceptor()); + } + + public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException { + throw SQLError.notImplemented(); + } + + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + throw SQLError.notImplemented(); + } + + public Properties getClientInfo() throws SQLException { + return getClientInfoProviderImpl().getClientInfo(this); + } + + public String getClientInfo(String name) throws SQLException { + return getClientInfoProviderImpl().getClientInfo(this, name); + } + + /** + * Returns true if the connection has not been closed and is still valid. + * The driver shall submit a query on the connection or use some other + * mechanism that positively verifies the connection is still valid when + * this method is called. + *

+ * The query submitted by the driver to validate the connection shall be + * executed in the context of the current transaction. + * + * @param timeout - The time in seconds to wait for the database operation + * used to validate the connection to complete. If + * the timeout period expires before the operation + * completes, this method returns false. A value of + * 0 indicates a timeout is not applied to the + * database operation. + *

+ * @return true if the connection is valid, false otherwise + * @exception SQLException if the value supplied for timeout + * is less then 0 + * @since 1.6 + */ + public boolean isValid(int timeout) throws SQLException { + synchronized (getConnectionMutex()) { + if (isClosed()) { + return false; + } + + try { + try { + pingInternal(false, timeout * 1000); + } catch (Throwable t) { + try { + abortInternal(); + } catch (Throwable ignoreThrown) { + // we're dead now anyway + } + + return false; + } + + } catch (Throwable t) { + return false; + } + + return true; + } + } + + public void setClientInfo(Properties properties) throws SQLClientInfoException { + try { + getClientInfoProviderImpl().setClientInfo(this, properties); + } catch (SQLClientInfoException ciEx) { + throw ciEx; + } catch (SQLException sqlEx) { + SQLClientInfoException clientInfoEx = new SQLClientInfoException(); + clientInfoEx.initCause(sqlEx); + + throw clientInfoEx; + } + } + + public void setClientInfo(String name, String value) throws SQLClientInfoException { + try { + getClientInfoProviderImpl().setClientInfo(this, name, value); + } catch (SQLClientInfoException ciEx) { + throw ciEx; + } catch (SQLException sqlEx) { + SQLClientInfoException clientInfoEx = new SQLClientInfoException(); + clientInfoEx.initCause(sqlEx); + + throw clientInfoEx; + } + } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public T unwrap(java.lang.Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return iface.cast(this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + /** + * @see java.sql.Connection#createBlob() + */ + public Blob createBlob() { + return new com.mysql.jdbc.Blob(getExceptionInterceptor()); + } + + /** + * @see java.sql.Connection#createClob() + */ + public Clob createClob() { + return new com.mysql.jdbc.Clob(getExceptionInterceptor()); + } + + /** + * @see java.sql.Connection#createNClob() + */ + public NClob createNClob() { + return new com.mysql.jdbc.JDBC4NClob(getExceptionInterceptor()); + } + + protected JDBC4ClientInfoProvider getClientInfoProviderImpl() throws SQLException { + synchronized (getConnectionMutex()) { + if (this.infoProvider == null) { + try { + try { + this.infoProvider = (JDBC4ClientInfoProvider)Util.getInstance(getClientInfoProvider(), + new Class[0], new Object[0], getExceptionInterceptor()); + } catch (SQLException sqlEx) { + if (sqlEx.getCause() instanceof ClassCastException) { + // try with package name prepended + this.infoProvider = (JDBC4ClientInfoProvider)Util.getInstance( + "com.mysql.jdbc." + getClientInfoProvider(), + new Class[0], new Object[0], getExceptionInterceptor()); + } + } + } catch (ClassCastException cce) { + throw SQLError.createSQLException(Messages + .getString("JDBC4Connection.ClientInfoNotImplemented", new Object[] {getClientInfoProvider()}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + this.infoProvider.initialize(this, this.props); + } + + return this.infoProvider; + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4DatabaseMetaData.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4DatabaseMetaData.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4DatabaseMetaData.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,174 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.ResultSet; +import java.sql.RowIdLifetime; +import java.sql.SQLException; +import java.sql.Types; +import java.util.ArrayList; + +import java.util.List; + +import com.mysql.jdbc.Field; + +public class JDBC4DatabaseMetaData extends DatabaseMetaData { + public JDBC4DatabaseMetaData(MySQLConnection connToSet, String databaseToSet) { + super(connToSet, databaseToSet); + } + + public RowIdLifetime getRowIdLifetime() throws SQLException { + return RowIdLifetime.ROWID_UNSUPPORTED; + } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public T unwrap(java.lang.Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return iface.cast(this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.conn.getExceptionInterceptor()); + } + } + + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return false; + } + + /** + * Changes in behavior introduced in JDBC4 when #getFunctionColumns became available. Overrides + * DatabaseMetaData#getProcedureColumns + * + * @see DatabaseMetaData#getProcedureColumns + * @since 1.6 + */ + public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, + String columnNamePattern) throws SQLException { + Field[] fields = createProcedureColumnsFields(); + + return getProcedureOrFunctionColumns(fields, catalog, schemaPattern, procedureNamePattern, columnNamePattern, + true, conn.getGetProceduresReturnsFunctions()); + } + + /** + * Changes in behavior introduced in JDBC4 when #getFunctions became available. Overrides + * DatabaseMetaData#getProcedures. + * + * @see DatabaseMetaData#getProcedures + * @since 1.6 + */ + public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) + throws SQLException { + Field[] fields = createFieldMetadataForGetProcedures(); + + return getProceduresAndOrFunctions(fields, catalog, schemaPattern, procedureNamePattern, true, + conn.getGetProceduresReturnsFunctions()); + } + + /** + * Overrides DatabaseMetaData#getJDBC4FunctionNoTableConstant. + * + * @return java.sql.DatabaseMetaData#functionNoTable + */ + protected int getJDBC4FunctionNoTableConstant() { + return functionNoTable; + } + + /** + * This method overrides DatabaseMetaData#getColumnType(boolean, boolean, boolean, boolean). + * + * @see JDBC4DatabaseMetaData#getProcedureOrFunctionColumnType(boolean, boolean, boolean, boolean) + */ + protected int getColumnType(boolean isOutParam, boolean isInParam, boolean isReturnParam, + boolean forGetFunctionColumns) { + return JDBC4DatabaseMetaData.getProcedureOrFunctionColumnType(isOutParam, isInParam, isReturnParam, + forGetFunctionColumns); + } + + /** + * Determines the COLUMN_TYPE information based on parameter type (IN, OUT or INOUT) or function return parameter. + * + * @param isOutParam + * Indicates whether it's an output parameter. + * @param isInParam + * Indicates whether it's an input parameter. + * @param isReturnParam + * Indicates whether it's a function return parameter. + * @param forGetFunctionColumns + * Indicates whether the column belong to a function. + * + * @return The corresponding COLUMN_TYPE as in java.sql.getProcedureColumns API. + */ + protected static int getProcedureOrFunctionColumnType(boolean isOutParam, boolean isInParam, boolean isReturnParam, + boolean forGetFunctionColumns) { + + if (isInParam && isOutParam) { + return forGetFunctionColumns ? functionColumnInOut : procedureColumnInOut; + } else if (isInParam) { + return forGetFunctionColumns ? functionColumnIn : procedureColumnIn; + } else if (isOutParam) { + return forGetFunctionColumns ? functionColumnOut : procedureColumnOut; + } else if (isReturnParam) { + return forGetFunctionColumns ? functionReturn : procedureColumnReturn; + } else { + return forGetFunctionColumns ? functionColumnUnknown : procedureColumnUnknown; + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,179 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.ResultSet; +import java.sql.RowIdLifetime; +import java.sql.SQLException; +import java.sql.Types; +import java.util.ArrayList; + +import java.util.List; + +import com.mysql.jdbc.Field; + +public class JDBC4DatabaseMetaDataUsingInfoSchema extends DatabaseMetaDataUsingInfoSchema { + public JDBC4DatabaseMetaDataUsingInfoSchema(MySQLConnection connToSet, String databaseToSet) throws SQLException { + super(connToSet, databaseToSet); + } + + public RowIdLifetime getRowIdLifetime() throws SQLException { + return RowIdLifetime.ROWID_UNSUPPORTED; + } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public T unwrap(java.lang.Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return iface.cast(this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.conn.getExceptionInterceptor()); + } + } + + /** + * Redirects to another implementation of #getProcedureColumns. Overrides + * DatabaseMetaDataUsingInfoSchema#getProcedureColumnsNoISParametersView. + * + * @see DatabaseMetaDataUsingInfoSchema#getProcedureColumns + * @see DatabaseMetaDataUsingInfoSchema#getProcedureColumnsNoISParametersView + */ + protected ResultSet getProcedureColumnsNoISParametersView(String catalog, String schemaPattern, + String procedureNamePattern, String columnNamePattern) throws SQLException { + Field[] fields = createProcedureColumnsFields(); + + return getProcedureOrFunctionColumns(fields, catalog, schemaPattern, procedureNamePattern, columnNamePattern, + true, conn.getGetProceduresReturnsFunctions()); + } + + /** + * Returns a condition to be injected in the query that returns metadata for procedures only. Overrides + * DatabaseMetaDataUsingInfoSchema#injectRoutineTypeConditionForGetProcedures. When not empty must end with "AND ". + * + * @return String with the condition to be injected. + */ + protected String getRoutineTypeConditionForGetProcedures() { + return conn.getGetProceduresReturnsFunctions() ? "" : "ROUTINE_TYPE = 'PROCEDURE' AND "; + } + + /** + * Returns a condition to be injected in the query that returns metadata for procedure columns only. Overrides + * DatabaseMetaDataUsingInfoSchema#injectRoutineTypeConditionForGetProcedureColumns. When not empty must end with + * "AND ". + * + * @return String with the condition to be injected. + */ + protected String getRoutineTypeConditionForGetProcedureColumns() { + return conn.getGetProceduresReturnsFunctions() ? "" : "ROUTINE_TYPE = 'PROCEDURE' AND "; + } + + /** + * Overrides DatabaseMetaDataUsingInfoSchema#getJDBC4FunctionConstant. + * + * @param constant + * the constant id from DatabaseMetaData fields to return. + * + * @return one of the java.sql.DatabaseMetaData#function* fields. + */ + protected int getJDBC4FunctionConstant(JDBC4FunctionConstant constant) { + switch (constant) { + case FUNCTION_COLUMN_IN: + return functionColumnIn; + case FUNCTION_COLUMN_INOUT: + return functionColumnInOut; + case FUNCTION_COLUMN_OUT: + return functionColumnOut; + case FUNCTION_COLUMN_RETURN: + return functionReturn; + case FUNCTION_COLUMN_RESULT: + return functionColumnResult; + case FUNCTION_COLUMN_UNKNOWN: + return functionColumnUnknown; + case FUNCTION_NO_NULLS: + return functionNoNulls; + case FUNCTION_NULLABLE: + return functionNullable; + case FUNCTION_NULLABLE_UNKNOWN: + return functionNullableUnknown; + default: + return -1; + } + } + + /** + * Overrides DatabaseMetaDataUsingInfoSchema#getJDBC4FunctionNoTableConstant. + * + * @return java.sql.DatabaseMetaData#functionNoTable. + */ + protected int getJDBC4FunctionNoTableConstant() { + return functionNoTable; + } + + /** + * Overrides DatabaseMetaData#getColumnType(boolean, boolean, boolean, boolean). + * + * @see JDBC4DatabaseMetaData#getProcedureOrFunctionColumnType(boolean, boolean, boolean, boolean) + */ + protected int getColumnType(boolean isOutParam, boolean isInParam, boolean isReturnParam, + boolean forGetFunctionColumns) { + return JDBC4DatabaseMetaData.getProcedureOrFunctionColumnType(isOutParam, isInParam, isReturnParam, + forGetFunctionColumns); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4LoadBalancedMySQLConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4LoadBalancedMySQLConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4LoadBalancedMySQLConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,136 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.Blob; +import java.sql.Clob; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.NClob; +import java.sql.Struct; +import java.util.Properties; +import java.util.TimerTask; + + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.Messages; +import com.mysql.jdbc.SQLError; + + +public class JDBC4LoadBalancedMySQLConnection extends + LoadBalancedMySQLConnection implements JDBC4MySQLConnection { + + public JDBC4LoadBalancedMySQLConnection(LoadBalancingConnectionProxy proxy) throws SQLException { + super(proxy); + } + + private JDBC4Connection getJDBC4Connection(){ + return (JDBC4Connection)this.proxy.currentConn; + } + public SQLXML createSQLXML() throws SQLException { + return this.getJDBC4Connection().createSQLXML(); + } + + public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return this.getJDBC4Connection(). createArrayOf(typeName, elements); + } + + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return this.getJDBC4Connection().createStruct(typeName, attributes); + } + + public Properties getClientInfo() throws SQLException { + return this.getJDBC4Connection().getClientInfo(); + } + + public String getClientInfo(String name) throws SQLException { + return this.getJDBC4Connection().getClientInfo(name); + } + + public boolean isValid(int timeout) throws SQLException { + synchronized (proxy) { + return this.getJDBC4Connection().isValid(timeout); + } + } + + + public void setClientInfo(Properties properties) throws SQLClientInfoException { + this.getJDBC4Connection().setClientInfo(properties); + } + + public void setClientInfo(String name, String value) throws SQLClientInfoException { + this.getJDBC4Connection().setClientInfo(name, value); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + + public T unwrap(java.lang.Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return iface.cast(this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + /** + * @see java.sql.Connection#createBlob() + */ + public Blob createBlob() { + return this.getJDBC4Connection().createBlob(); + } + + /** + * @see java.sql.Connection#createClob() + */ + public Clob createClob() { + return this.getJDBC4Connection().createClob(); + } + + /** + * @see java.sql.Connection#createNClob() + */ + public NClob createNClob() { + return this.getJDBC4Connection().createNClob(); + } + + protected JDBC4ClientInfoProvider getClientInfoProviderImpl() throws SQLException { + synchronized (proxy) { + return this.getJDBC4Connection().getClientInfoProviderImpl(); + } + + } + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4MySQLConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4MySQLConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4MySQLConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,71 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.Blob; +import java.sql.Clob; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.NClob; +import java.sql.Struct; +import java.util.Properties; +import java.util.TimerTask; + + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.Messages; +import com.mysql.jdbc.SQLError; + + +public interface JDBC4MySQLConnection extends MySQLConnection { + + public SQLXML createSQLXML() throws SQLException; + + public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException; + + public Struct createStruct(String typeName, Object[] attributes) throws SQLException; + + public Properties getClientInfo() throws SQLException; + + public String getClientInfo(String name) throws SQLException; + + public boolean isValid(int timeout) throws SQLException; + + public void setClientInfo(Properties properties) throws SQLClientInfoException; + + public void setClientInfo(String name, String value) throws SQLClientInfoException; + + public boolean isWrapperFor(Class iface) throws SQLException; + + public T unwrap(java.lang.Class iface) throws java.sql.SQLException; + + public Blob createBlob(); + + public Clob createClob(); + + public NClob createNClob(); + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4MysqlSQLXML.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4MysqlSQLXML.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4MysqlSQLXML.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,837 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLXML; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stax.StAXResult; +import javax.xml.transform.stax.StAXSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.SAXException; + + + +public class JDBC4MysqlSQLXML implements SQLXML { + + private XMLInputFactory inputFactory; + + private XMLOutputFactory outputFactory; + + private String stringRep; + + private ResultSetInternalMethods owningResultSet; + + private int columnIndexOfXml; + + private boolean fromResultSet; + + private boolean isClosed = false; + + private boolean workingWithResult; + + private DOMResult asDOMResult; + + private SAXResult asSAXResult; + + private SimpleSaxToReader saxToReaderConverter; + + private StringWriter asStringWriter; + + private ByteArrayOutputStream asByteArrayOutputStream; + + private ExceptionInterceptor exceptionInterceptor; + + protected JDBC4MysqlSQLXML(ResultSetInternalMethods owner, int index, ExceptionInterceptor exceptionInterceptor) { + this.owningResultSet = owner; + this.columnIndexOfXml = index; + this.fromResultSet = true; + this.exceptionInterceptor = exceptionInterceptor; + } + + protected JDBC4MysqlSQLXML(ExceptionInterceptor exceptionInterceptor) { + this.fromResultSet = false; + this.exceptionInterceptor = exceptionInterceptor; + } + + public synchronized void free() throws SQLException { + this.stringRep = null; + this.asDOMResult = null; + this.asSAXResult = null; + this.inputFactory = null; + this.outputFactory = null; + this.owningResultSet = null; + this.workingWithResult = false; + this.isClosed = true; + + } + + public synchronized String getString() throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + if (this.fromResultSet) { + return this.owningResultSet.getString(this.columnIndexOfXml); + } + + return this.stringRep; + } + + private synchronized void checkClosed() throws SQLException { + if (this.isClosed) { + throw SQLError + .createSQLException("SQLXMLInstance has been free()d", this.exceptionInterceptor); + } + } + + private synchronized void checkWorkingWithResult() throws SQLException { + if (this.workingWithResult) { + throw SQLError + .createSQLException( + "Can't perform requested operation after getResult() has been called to write XML data", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } + + /** + * Sets the XML value designated by this SQLXML instance to the given String + * representation. The format of this String is defined by + * org.xml.sax.InputSource, where the characters in the stream represent the + * unicode code points for XML according to section 2 and appendix B of the + * XML 1.0 specification. Although an encoding declaration other than + * unicode may be present, the encoding of the String is unicode. The + * behavior of this method is the same as ResultSet.updateString() when the + * designated column of the ResultSet has a type java.sql.Types of SQLXML. + *

+ * The SQL XML object becomes not writeable when this method is called and + * may also become not readable depending on implementation. + * + * @param value + * the XML value + * @throws SQLException + * if there is an error processing the XML value. The getCause() + * method of the exception may provide a more detailed + * exception, for example, if the stream does not contain valid + * characters. An exception is thrown if the state is not + * writable. + * @exception SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @since 1.6 + */ + + public synchronized void setString(String str) throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + this.stringRep = str; + this.fromResultSet = false; + } + + public synchronized boolean isEmpty() throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + if (!this.fromResultSet) { + return this.stringRep == null || this.stringRep.length() == 0; + } + + return false; + } + + public synchronized InputStream getBinaryStream() throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + return this.owningResultSet.getBinaryStream(this.columnIndexOfXml); + } + + /** + * Retrieves the XML value designated by this SQLXML instance as a + * java.io.Reader object. The format of this stream is defined by + * org.xml.sax.InputSource, where the characters in the stream represent the + * unicode code points for XML according to section 2 and appendix B of the + * XML 1.0 specification. Although an encoding declaration other than + * unicode may be present, the encoding of the stream is unicode. The + * behavior of this method is the same as ResultSet.getCharacterStream() + * when the designated column of the ResultSet has a type java.sql.Types of + * SQLXML. + *

+ * The SQL XML object becomes not readable when this method is called and + * may also become not writable depending on implementation. + * + * @return a stream containing the XML data. + * @throws SQLException + * if there is an error processing the XML value. The getCause() + * method of the exception may provide a more detailed + * exception, for example, if the stream does not contain valid + * characters. An exception is thrown if the state is not + * readable. + * @exception SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @since 1.6 + */ + public synchronized Reader getCharacterStream() throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + return this.owningResultSet.getCharacterStream(this.columnIndexOfXml); + } + + /** + * Returns a Source for reading the XML value designated by this SQLXML + * instance. Sources are used as inputs to XML parsers and XSLT + * transformers. + *

+ * Sources for XML parsers will have namespace processing on by default. The + * systemID of the Source is implementation dependent. + *

+ * The SQL XML object becomes not readable when this method is called and + * may also become not writable depending on implementation. + *

+ * Note that SAX is a callback architecture, so a returned SAXSource should + * then be set with a content handler that will receive the SAX events from + * parsing. The content handler will receive callbacks based on the contents + * of the XML. + * + *

+	 * SAXSource saxSource = sqlxml.getSource(SAXSource.class);
+	 * XMLReader xmlReader = saxSource.getXMLReader();
+	 * xmlReader.setContentHandler(myHandler);
+	 * xmlReader.parse(saxSource.getInputSource());
+	 * 
+ * + * @param sourceClass + * The class of the source, or null. If the class is null, a + * vendor specifc Source implementation will be returned. The + * following classes are supported at a minimum: + * + * (MySQL returns a SAXSource if sourceClass == null) + * + *
+	 *    javax.xml.transform.dom.DOMSource - returns a DOMSource
+	 *    javax.xml.transform.sax.SAXSource - returns a SAXSource
+	 *    javax.xml.transform.stax.StAXSource - returns a StAXSource
+	 *    javax.xml.transform.stream.StreamSource - returns a StreamSource
+	 * 
+ * + * @return a Source for reading the XML value. + * @throws SQLException + * if there is an error processing the XML value or if this + * feature is not supported. The getCause() method of the + * exception may provide a more detailed exception, for example, + * if an XML parser exception occurs. An exception is thrown if + * the state is not readable. + * @exception SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @since 1.6 + */ + public synchronized Source getSource(Class clazz) throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + // Note that we try and use streams here wherever possible + // for the day that the server actually supports streaming + // from server -> client (futureproofing) + + if (clazz == null || clazz.equals(SAXSource.class)) { + + InputSource inputSource = null; + + if (this.fromResultSet) { + inputSource = new InputSource(this.owningResultSet + .getCharacterStream(this.columnIndexOfXml)); + } else { + inputSource = new InputSource(new StringReader(this.stringRep)); + } + + return new SAXSource(inputSource); + } else if (clazz.equals(DOMSource.class)) { + try { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory + .newInstance(); + builderFactory.setNamespaceAware(true); + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + InputSource inputSource = null; + + if (this.fromResultSet) { + inputSource = new InputSource(this.owningResultSet + .getCharacterStream(this.columnIndexOfXml)); + } else { + inputSource = new InputSource(new StringReader( + this.stringRep)); + } + + return new DOMSource(builder.parse(inputSource)); + } catch (Throwable t) { + SQLException sqlEx = SQLError.createSQLException(t + .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(t); + + throw sqlEx; + } + + } else if (clazz.equals(StreamSource.class)) { + Reader reader = null; + + if (this.fromResultSet) { + reader = this.owningResultSet + .getCharacterStream(this.columnIndexOfXml); + } else { + reader = new StringReader(this.stringRep); + } + + return new StreamSource(reader); + } else if (clazz.equals(StAXSource.class)) { + try { + Reader reader = null; + + if (this.fromResultSet) { + reader = this.owningResultSet + .getCharacterStream(this.columnIndexOfXml); + } else { + reader = new StringReader(this.stringRep); + } + + return new StAXSource(this.inputFactory + .createXMLStreamReader(reader)); + } catch (XMLStreamException ex) { + SQLException sqlEx = SQLError.createSQLException(ex + .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(ex); + + throw sqlEx; + } + } else { + throw SQLError.createSQLException("XML Source of type \"" + + clazz.toString() + "\" Not supported.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } + + /** + * Retrieves a stream that can be used to write the XML value that this + * SQLXML instance represents. The stream begins at position 0. The bytes of + * the stream are interpreted according to appendix F of the XML 1.0 + * specification The behavior of this method is the same as + * ResultSet.updateBinaryStream() when the designated column of the + * ResultSet has a type java.sql.Types of SQLXML. + *

+ * The SQL XML object becomes not writeable when this method is called and + * may also become not readable depending on implementation. + * + * @return a stream to which data can be written. + * @throws SQLException + * if there is an error processing the XML value. An exception + * is thrown if the state is not writable. + * @exception SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @since 1.6 + */ + public synchronized OutputStream setBinaryStream() throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + this.workingWithResult = true; + + return setBinaryStreamInternal(); + } + + private synchronized OutputStream setBinaryStreamInternal() + throws SQLException { + this.asByteArrayOutputStream = new ByteArrayOutputStream(); + + return this.asByteArrayOutputStream; + } + + /** + * Retrieves a stream to be used to write the XML value that this SQLXML + * instance represents. The format of this stream is defined by + * org.xml.sax.InputSource, where the characters in the stream represent the + * unicode code points for XML according to section 2 and appendix B of the + * XML 1.0 specification. Although an encoding declaration other than + * unicode may be present, the encoding of the stream is unicode. The + * behavior of this method is the same as ResultSet.updateCharacterStream() + * when the designated column of the ResultSet has a type java.sql.Types of + * SQLXML. + *

+ * The SQL XML object becomes not writeable when this method is called and + * may also become not readable depending on implementation. + * + * @return a stream to which data can be written. + * @throws SQLException + * if there is an error processing the XML value. The getCause() + * method of the exception may provide a more detailed + * exception, for example, if the stream does not contain valid + * characters. An exception is thrown if the state is not + * writable. + * @exception SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @since 1.6 + */ + public synchronized Writer setCharacterStream() throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + this.workingWithResult = true; + + return setCharacterStreamInternal(); + } + + private synchronized Writer setCharacterStreamInternal() + throws SQLException { + this.asStringWriter = new StringWriter(); + + return this.asStringWriter; + } + + /** + * Returns a Result for setting the XML value designated by this SQLXML + * instance. + *

+ * The systemID of the Result is implementation dependent. + *

+ * The SQL XML object becomes not writeable when this method is called and + * may also become not readable depending on implementation. + *

+ * Note that SAX is a callback architecture and the returned SAXResult has a + * content handler assigned that will receive the SAX events based on the + * contents of the XML. Call the content handler with the contents of the + * XML document to assign the values. + * + *

+	 * SAXResult saxResult = sqlxml.setResult(SAXResult.class);
+	 * ContentHandler contentHandler = saxResult.getXMLReader().getContentHandler();
+	 * contentHandler.startDocument();
+	 * // set the XML elements and attributes into the result
+	 * contentHandler.endDocument();
+	 * 
+ * + * @param resultClass + * The class of the result, or null. If resultClass is null, a + * vendor specific Result implementation will be returned. The + * following classes are supported at a minimum: + * + *
+	 *    javax.xml.transform.dom.DOMResult - returns a DOMResult
+	 *    javax.xml.transform.sax.SAXResult - returns a SAXResult
+	 *    javax.xml.transform.stax.StAXResult - returns a StAXResult
+	 *    javax.xml.transform.stream.StreamResult - returns a StreamResult
+	 * 
+ * + * @return Returns a Result for setting the XML value. + * @throws SQLException + * if there is an error processing the XML value or if this + * feature is not supported. The getCause() method of the + * exception may provide a more detailed exception, for example, + * if an XML parser exception occurs. An exception is thrown if + * the state is not writable. + * @exception SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @since 1.6 + */ + public synchronized Result setResult(Class clazz) throws SQLException { + checkClosed(); + checkWorkingWithResult(); + + this.workingWithResult = true; + this.asDOMResult = null; + this.asSAXResult = null; + this.saxToReaderConverter = null; + this.stringRep = null; + this.asStringWriter = null; + this.asByteArrayOutputStream = null; + + if (clazz == null || clazz.equals(SAXResult.class)) { + this.saxToReaderConverter = new SimpleSaxToReader(); + + this.asSAXResult = new SAXResult(this.saxToReaderConverter); + + return this.asSAXResult; + } else if (clazz.equals(DOMResult.class)) { + + this.asDOMResult = new DOMResult(); + return this.asDOMResult; + + } else if (clazz.equals(StreamResult.class)) { + return new StreamResult(setCharacterStreamInternal()); + } else if (clazz.equals(StAXResult.class)) { + try { + if (this.outputFactory == null) { + this.outputFactory = XMLOutputFactory.newInstance(); + } + + return new StAXResult(this.outputFactory + .createXMLEventWriter(setCharacterStreamInternal())); + } catch (XMLStreamException ex) { + SQLException sqlEx = SQLError.createSQLException(ex + .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(ex); + + throw sqlEx; + } + } else { + throw SQLError.createSQLException("XML Result of type \"" + + clazz.toString() + "\" Not supported.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } + + private Reader binaryInputStreamStreamToReader(ByteArrayOutputStream out) { + + try { + // There's got to be an easier way to do this, but + // I don't feel like coding up Appendix F of the XML Spec + // myself, when there's a reusable way to do it, and we + // can warn folks away from BINARY xml streams that have + // to be parsed to determine the character encoding :P + + String encoding = "UTF-8"; + + try { + ByteArrayInputStream bIn = new ByteArrayInputStream(out + .toByteArray()); + XMLStreamReader reader = this.inputFactory + .createXMLStreamReader(bIn); + + int eventType = 0; + + while ((eventType = reader.next()) != XMLStreamReader.END_DOCUMENT) { + if (eventType == XMLStreamReader.START_DOCUMENT) { + String possibleEncoding = reader.getEncoding(); + + if (possibleEncoding != null) { + encoding = possibleEncoding; + } + + break; + } + } + } catch (Throwable t) { + // ignore, dealt with later when the string can't be parsed + // into valid XML + } + + return new StringReader(new String(out.toByteArray(), encoding)); + } catch (UnsupportedEncodingException badEnc) { + throw new RuntimeException(badEnc); + } + } + + protected String readerToString(Reader reader) throws SQLException { + StringBuffer buf = new StringBuffer(); + + int charsRead = 0; + + char[] charBuf = new char[512]; + + try { + while ((charsRead = reader.read(charBuf)) != -1) { + buf.append(charBuf, 0, charsRead); + } + } catch (IOException ioEx) { + SQLException sqlEx = SQLError.createSQLException(ioEx + .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(ioEx); + + throw sqlEx; + } + + return buf.toString(); + } + + protected synchronized Reader serializeAsCharacterStream() + throws SQLException { + checkClosed(); + if (this.workingWithResult) { + // figure out what kind of result + if (this.stringRep != null) { + return new StringReader(this.stringRep); + } + + if (this.asDOMResult != null) { + return new StringReader(domSourceToString()); + } + + if (this.asStringWriter != null) { // stax result + return new StringReader(this.asStringWriter.toString()); + } + + if (this.asSAXResult != null) { + return this.saxToReaderConverter.toReader(); + } + + if (this.asByteArrayOutputStream != null) { + return binaryInputStreamStreamToReader(this.asByteArrayOutputStream); + } + } + + return this.owningResultSet.getCharacterStream(this.columnIndexOfXml); + } + + protected String domSourceToString() throws SQLException { + try { + DOMSource source = new DOMSource(this.asDOMResult.getNode()); + Transformer identity = TransformerFactory.newInstance() + .newTransformer(); + StringWriter stringOut = new StringWriter(); + Result result = new StreamResult(stringOut); + identity.transform(source, result); + + return stringOut.toString(); + } catch (Throwable t) { + SQLException sqlEx = SQLError.createSQLException(t + .getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(t); + + throw sqlEx; + } + } + + protected synchronized String serializeAsString() throws SQLException { + checkClosed(); + if (this.workingWithResult) { + // figure out what kind of result + if (this.stringRep != null) { + return this.stringRep; + } + + if (this.asDOMResult != null) { + return domSourceToString(); + } + + if (this.asStringWriter != null) { // stax result + return this.asStringWriter.toString(); + } + + if (this.asSAXResult != null) { + return readerToString(this.saxToReaderConverter.toReader()); + } + + if (this.asByteArrayOutputStream != null) { + return readerToString( + binaryInputStreamStreamToReader(this.asByteArrayOutputStream)); + } + } + + return this.owningResultSet.getString(this.columnIndexOfXml); + } + + /* + * The SimpleSaxToReader class is an adaptation of the SAX "Writer" + * example from the Apache XercesJ-2 Project. The license for this + * code is as follows: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + class SimpleSaxToReader extends DefaultHandler { + StringBuffer buf = new StringBuffer(); + + public void startDocument() throws SAXException { + buf.append(""); + } + + public void endDocument() throws SAXException { + // Do we need to override this? + } + + public void startElement(String namespaceURI, String sName, + String qName, Attributes attrs) throws SAXException { + + this.buf.append("<"); + this.buf.append(qName); + + if (attrs != null) { + for (int i = 0; i < attrs.getLength(); i++) { + this.buf.append(" "); + this.buf.append(attrs.getQName(i)).append("=\""); + escapeCharsForXml(attrs.getValue(i), true); + this.buf.append("\""); + } + } + + this.buf.append(">"); + } + + public void characters(char buf[], int offset, int len) + throws SAXException { + if (!this.inCDATA) { + escapeCharsForXml(buf, offset, len, false); + } else { + this.buf.append(buf, offset, len); + } + } + + public void ignorableWhitespace(char ch[], int start, int length) + throws SAXException { + characters(ch, start, length); + } + + private boolean inCDATA = false; + + public void startCDATA() throws SAXException { + this.buf.append(""); + } + + public void comment(char ch[], int start, int length) + throws SAXException { + // if (!fCanonical && fElementDepth > 0) { + this.buf.append(""); + // } + } + + Reader toReader() { + return new StringReader(this.buf.toString()); + } + + private void escapeCharsForXml(String str, boolean isAttributeData) { + if (str == null) { + return; + } + + int strLen = str.length(); + + for (int i = 0; i < strLen; i++) { + escapeCharsForXml(str.charAt(i), isAttributeData); + } + } + + private void escapeCharsForXml(char[] buf, int offset, int len, + boolean isAttributeData) { + + if (buf == null) { + return; + } + + for (int i = 0; i < len; i++) { + escapeCharsForXml(buf[offset + i], isAttributeData); + } + } + + private void escapeCharsForXml(char c, boolean isAttributeData) { + switch (c) { + case '<': + this.buf.append("<"); + break; + + case '>': + this.buf.append(">"); + break; + + case '&': + this.buf.append("&"); + break; + + case '"': + + if (!isAttributeData) { + this.buf.append("\""); + } + else { + this.buf.append("""); + } + + break; + + case '\r': + this.buf.append(" "); + break; + + + default: + + if (((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A) + || (c >= 0x7F && c <= 0x9F) || c == 0x2028) + || isAttributeData && (c == 0x09 || c == 0x0A)) { + this.buf.append("&#x"); + this.buf.append(Integer.toHexString(c).toUpperCase()); + this.buf.append(";"); + } + else { + this.buf.append(c); + } + } + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4NClob.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4NClob.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4NClob.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,44 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import com.mysql.jdbc.ExceptionInterceptor; + + +/** + * Simplistic implementation of java.sql.NClob for MySQL Connector/J + * + * @author Tetsuro Ikeda + * @version $Id$ + */ +public class JDBC4NClob extends Clob implements java.sql.NClob { + + JDBC4NClob(ExceptionInterceptor exceptionInterceptor) { + super(exceptionInterceptor); + } + + JDBC4NClob(String charDataInit, ExceptionInterceptor exceptionInterceptor) { + super(charDataInit, exceptionInterceptor); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4PreparedStatement.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4PreparedStatement.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4PreparedStatement.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,78 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.NClob; +import java.sql.RowId; +import java.sql.SQLXML; +import java.sql.SQLException; +import java.sql.Types; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.PreparedStatement; +import com.mysql.jdbc.PreparedStatement.ParseInfo; + + +public class JDBC4PreparedStatement extends PreparedStatement { + + public JDBC4PreparedStatement(MySQLConnection conn, String catalog) throws SQLException { + super(conn, catalog); + } + + public JDBC4PreparedStatement(MySQLConnection conn, String sql, String catalog) + throws SQLException { + super(conn, sql, catalog); + } + + public JDBC4PreparedStatement(MySQLConnection conn, String sql, String catalog, + ParseInfo cachedParseInfo) throws SQLException { + super(conn, sql, catalog, cachedParseInfo); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + JDBC4PreparedStatementHelper.setRowId(this, parameterIndex, x); + } + + /** + * JDBC 4.0 Set a NCLOB parameter. + * + * @param i + * the first parameter is 1, the second is 2, ... + * @param x + * an object representing a NCLOB + * + * @throws SQLException + * if a database error occurs + */ + public void setNClob(int parameterIndex, NClob value) throws SQLException { + JDBC4PreparedStatementHelper.setNClob(this, parameterIndex, value); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + JDBC4PreparedStatementHelper.setSQLXML(this, parameterIndex, xmlObject); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4PreparedStatementHelper.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4PreparedStatementHelper.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4PreparedStatementHelper.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,100 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.Reader; +import java.sql.NClob; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Types; + +import com.mysql.jdbc.PreparedStatement; + + +public class JDBC4PreparedStatementHelper { + private JDBC4PreparedStatementHelper() { + + } + + static void setRowId(PreparedStatement pstmt, int parameterIndex, RowId x) throws SQLException { + throw SQLError.notImplemented(); + } + + + /** + * JDBC 4.0 Set a NCLOB parameter. + * + * @param i + * the first parameter is 1, the second is 2, ... + * @param x + * an object representing a NCLOB + * + * @throws SQLException + * if a database error occurs + */ + static void setNClob(PreparedStatement pstmt, int parameterIndex, NClob value) throws SQLException { + if (value == null) { + pstmt.setNull(parameterIndex, java.sql.Types.NCLOB); + } else { + pstmt.setNCharacterStream(parameterIndex, value.getCharacterStream(), value.length()); + } + } + + static void setNClob(PreparedStatement pstmt, int parameterIndex, Reader reader) throws SQLException { + pstmt.setNCharacterStream(parameterIndex, reader); + } + + /** + * JDBC 4.0 Set a NCLOB parameter. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param reader + * the java reader which contains the UNICODE data + * @param length + * the number of characters in the stream + * + * @throws SQLException + * if a database error occurs + */ + static void setNClob(PreparedStatement pstmt, int parameterIndex, Reader reader, long length) + throws SQLException { + if (reader == null) { + pstmt.setNull(parameterIndex, java.sql.Types.NCLOB); + } else { + pstmt.setNCharacterStream(parameterIndex, reader, length); + } + } + + static void setSQLXML(PreparedStatement pstmt, int parameterIndex, SQLXML xmlObject) + throws SQLException { + if (xmlObject == null) { + pstmt.setNull(parameterIndex, Types.SQLXML); + } else { + // FIXME: Won't work for Non-MYSQL SQLXMLs + pstmt.setCharacterStream(parameterIndex, ((JDBC4MysqlSQLXML)xmlObject).serializeAsCharacterStream()); + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ResultSet.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ResultSet.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ResultSet.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,544 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.sql.NClob; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Struct; +import java.sql.SQLFeatureNotSupportedException; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.Field; +import com.mysql.jdbc.NotUpdatable; +import com.mysql.jdbc.ResultSetImpl; +import com.mysql.jdbc.RowData; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Statement; + + +public class JDBC4ResultSet extends ResultSetImpl { + + public JDBC4ResultSet(long updateCount, long updateID, + MySQLConnection conn, StatementImpl creatorStmt) { + super(updateCount, updateID, conn, creatorStmt); + } + + public JDBC4ResultSet(String catalog, Field[] fields, RowData tuples, + MySQLConnection conn, StatementImpl creatorStmt) throws SQLException { + super(catalog, fields, tuples, conn, creatorStmt); + } + + /** + * JDBC 4.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnIndex + * the column to get the value from + * + * @return the value in the column as a java.io.Reader. + * + * @throws SQLException + * if an error occurs + */ + public Reader getNCharacterStream(int columnIndex) throws SQLException { + checkColumnBounds(columnIndex); + + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call getNCharacterStream() when field's charset isn't UTF-8"); + } + return getCharacterStream(columnIndex); + } + + /** + * JDBC 4.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnName + * the column name to retrieve the value from + * + * @return the value as a java.io.Reader + * + * @throws SQLException + * if an error occurs + */ + public Reader getNCharacterStream(String columnName) throws SQLException { + return getNCharacterStream(findColumn(columnName)); + } + + /** + * JDBC 4.0 Get a NCLOB column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing a NCLOB + * + * @throws SQLException + * if an error occurs + */ + public NClob getNClob(int columnIndex) throws SQLException { + checkColumnBounds(columnIndex); + + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call getNClob() when field's charset isn't UTF-8"); + } + if (!this.isBinaryEncoded) { + String asString = getStringForNClob(columnIndex); + + if (asString == null) { + return null; + } + + return new com.mysql.jdbc.JDBC4NClob(asString, getExceptionInterceptor()); + } + + return getNativeNClob(columnIndex); + } + + /** + * JDBC 4.0 Get a NCLOB column. + * + * @param colName + * the column name + * + * @return an object representing a NCLOB + * + * @throws SQLException + * if an error occurs + */ + public NClob getNClob(String columnName) throws SQLException { + return getNClob(findColumn(columnName)); + } + + /** + * JDBC 4.0 Get a NCLOB column. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return an object representing a NCLOB + * + * @throws SQLException + * if an error occurs + */ + protected java.sql.NClob getNativeNClob(int columnIndex) + throws SQLException { + String stringVal = getStringForNClob(columnIndex); + + if (stringVal == null) { + return null; + } + + return getNClobFromString(stringVal, columnIndex); + } + + private String getStringForNClob(int columnIndex) throws SQLException { + String asString = null; + + String forcedEncoding = "UTF-8"; + + try { + byte[] asBytes = null; + + if (!this.isBinaryEncoded) { + asBytes = getBytes(columnIndex); + } else { + asBytes = getNativeBytes(columnIndex, true); + } + + if (asBytes != null) { + asString = new String(asBytes, forcedEncoding); + } + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException("Unsupported character encoding " + + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return asString; + } + + private final java.sql.NClob getNClobFromString(String stringVal, + int columnIndex) throws SQLException { + return new com.mysql.jdbc.JDBC4NClob(stringVal, getExceptionInterceptor()); + } + + /** + * JDBC 4.0 + * + * Get the value of a column in the current row as a Java String + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value, null for SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public String getNString(int columnIndex) throws SQLException { + checkColumnBounds(columnIndex); + + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call getNString() when field's charset isn't UTF-8"); + } + return getString(columnIndex); + } + + /** + * JDBC 4.0 + * + * The following routines simply convert the columnName into a columnIndex + * and then call the appropriate routine above. + * + * @param columnName + * is the SQL name of the column + * + * @return the column value + * + * @exception SQLException + * if a database access error occurs + */ + public String getNString(String columnName) throws SQLException { + return getNString(findColumn(columnName)); + } + + /** + * JDBC 4.0 Update a column with a character stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param length + * the length of the stream + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateNCharacterStream(int columnIndex, Reader x, int length) + throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 4.0 Update a column with a character stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnName + * the name of the column + * @param reader + * the stream to update the column with + * @param length + * of the stream + * + * @throws SQLException + * if a database-access error occurs + */ + public void updateNCharacterStream(String columnName, Reader reader, + int length) throws SQLException { + updateNCharacterStream(findColumn(columnName), reader, length); + } + + /** + * @see ResultSet#updateNClob(String, NClob) + */ + public void updateNClob(String columnName, NClob nClob) throws SQLException { + updateNClob(findColumn(columnName), nClob); + } + + public void updateRowId(int columnIndex, RowId x) throws SQLException { + throw new NotUpdatable(); + } + + public void updateRowId(String columnName, RowId x) throws SQLException { + updateRowId(findColumn(columnName), x); + } + + public int getHoldability() throws SQLException { + throw SQLError.notImplemented(); + } + + public RowId getRowId(int columnIndex) throws SQLException { + throw SQLError.notImplemented(); + } + + public RowId getRowId(String columnLabel) throws SQLException { + return getRowId(findColumn(columnLabel)); + } + + public SQLXML getSQLXML(int columnIndex) throws SQLException { + checkColumnBounds(columnIndex); + + return new JDBC4MysqlSQLXML(this, columnIndex, getExceptionInterceptor()); + } + + public SQLXML getSQLXML(String columnLabel) throws SQLException { + return getSQLXML(findColumn(columnLabel)); + } + + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { + updateAsciiStream(findColumn(columnLabel), x); + + } + + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { + updateAsciiStream(findColumn(columnLabel), x, length); + } + + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { + updateBinaryStream(findColumn(columnLabel), x); + } + + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { + updateBinaryStream(findColumn(columnLabel), x, length); + } + + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { + throw new NotUpdatable(); + } + + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { + updateBlob(findColumn(columnLabel), inputStream); + } + + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { + updateBlob(findColumn(columnLabel), inputStream, length); + } + + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { + updateCharacterStream(findColumn(columnLabel), reader); + } + + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + updateCharacterStream(findColumn(columnLabel), reader, length); + } + + public void updateClob(int columnIndex, Reader reader) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateClob(String columnLabel, Reader reader) throws SQLException { + updateClob(findColumn(columnLabel), reader); + } + + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { + updateClob(findColumn(columnLabel), reader, length); + } + + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { + updateNCharacterStream(findColumn(columnLabel), reader); + + } + + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + updateNCharacterStream(findColumn(columnLabel), reader, length); + } + + public void updateNClob(int columnIndex, NClob nClob) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNClob(int columnIndex, Reader reader) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + updateNClob(findColumn(columnLabel), reader); + + } + + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { + throw new NotUpdatable(); + } + + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { + updateNClob(findColumn(columnLabel), reader, length); + } + + public void updateNString(int columnIndex, String nString) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNString(String columnLabel, String nString) throws SQLException { + updateNString(findColumn(columnLabel), nString); + } + + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + updateSQLXML(findColumn(columnLabel), xmlObject); + + } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public T unwrap(java.lang.Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return iface.cast(this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + @SuppressWarnings("unchecked") + public T getObject(int columnIndex, Class type) throws SQLException { + if (type == null) { + throw SQLError.createSQLException("Type parameter can not be null", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (type.equals(Struct.class)) { + throw new SQLFeatureNotSupportedException(); + } else if (type.equals(RowId.class)) { + return (T) getRowId(columnIndex); + } else if (type.equals(NClob.class)) { + return (T) getNClob(columnIndex); + } else if (type.equals(SQLXML.class)) { + return (T) getSQLXML(columnIndex); + } + + return super.getObject(columnIndex, type); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ServerPreparedStatement.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ServerPreparedStatement.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4ServerPreparedStatement.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,151 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.Reader; +import java.sql.NClob; +import java.sql.RowId; +import java.sql.SQLXML; +import java.sql.SQLException; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.MysqlDefs; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.ServerPreparedStatement; +import com.mysql.jdbc.ServerPreparedStatement.BindValue; + +public class JDBC4ServerPreparedStatement extends ServerPreparedStatement { + + public JDBC4ServerPreparedStatement(MySQLConnection conn, String sql, + String catalog, int resultSetType, int resultSetConcurrency) + throws SQLException { + super(conn, sql, catalog, resultSetType, resultSetConcurrency); + // TODO Auto-generated constructor stub + } + + /** + * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader, + * long) + */ + public void setNCharacterStream(int parameterIndex, Reader reader, + long length) throws SQLException { + // can't take if characterEncoding isn't utf8 + if (!this.charEncoding.equalsIgnoreCase("UTF-8") + && !this.charEncoding.equalsIgnoreCase("utf8")) { + throw SQLError + .createSQLException("Can not call setNCharacterStream() when connection character set isn't UTF-8", getExceptionInterceptor()); + } + + checkClosed(); + + if (reader == null) { + setNull(parameterIndex, java.sql.Types.BINARY); + } else { + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = reader; + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = length; + } else { + binding.bindLength = -1; + } + } + } + + /** + * @see java.sql.PreparedStatement#setNClob(int, java.sql.NClob) + */ + public void setNClob(int parameterIndex, NClob x) throws SQLException { + setNClob(parameterIndex, x.getCharacterStream(), this.connection + .getUseStreamLengthsInPrepStmts() ? x.length() : -1); + } + + /** + * JDBC 4.0 Set a NCLOB parameter. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param reader + * the java reader which contains the UNICODE data + * @param length + * the number of characters in the stream + * + * @throws SQLException + * if a database error occurs + */ + public void setNClob(int parameterIndex, Reader reader, long length) + throws SQLException { + // can't take if characterEncoding isn't utf8 + if (!this.charEncoding.equalsIgnoreCase("UTF-8") + && !this.charEncoding.equalsIgnoreCase("utf8")) { + throw SQLError + .createSQLException("Can not call setNClob() when connection character set isn't UTF-8", getExceptionInterceptor()); + } + + checkClosed(); + + if (reader == null) { + setNull(parameterIndex, java.sql.Types.NCLOB); + } else { + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = reader; + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = length; + } else { + binding.bindLength = -1; + } + } + } + + /** + * @see java.sql.PreparedStatement#setNString(int, java.lang.String) + */ + public void setNString(int parameterIndex, String x) throws SQLException { + if (this.charEncoding.equalsIgnoreCase("UTF-8") + || this.charEncoding.equalsIgnoreCase("utf8")) { + setString(parameterIndex, x); + } else { + throw SQLError + .createSQLException("Can not call setNString() when connection character set isn't UTF-8", getExceptionInterceptor()); + } + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + JDBC4PreparedStatementHelper.setRowId(this, parameterIndex, x); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + JDBC4PreparedStatementHelper.setSQLXML(this, parameterIndex, xmlObject); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4UpdatableResultSet.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4UpdatableResultSet.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/JDBC4UpdatableResultSet.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,613 @@ +/* + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.sql.NClob; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.Field; +import com.mysql.jdbc.NotUpdatable; +import com.mysql.jdbc.RowData; +import com.mysql.jdbc.Statement; +import com.mysql.jdbc.StringUtils; +import com.mysql.jdbc.UpdatableResultSet; + + + +public class JDBC4UpdatableResultSet extends UpdatableResultSet { + public JDBC4UpdatableResultSet(String catalog, Field[] fields, RowData tuples, + MySQLConnection conn, StatementImpl creatorStmt) throws SQLException { + super(catalog, fields, tuples, conn, creatorStmt); + } + + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { + throw new NotUpdatable(); + } + + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { + throw new NotUpdatable(); + + } + + + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateClob(int columnIndex, Reader reader) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + updateNCharacterStream(columnIndex, x, (int) length); + + } + + + public void updateNClob(int columnIndex, Reader reader) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { + throw new NotUpdatable(); + } + + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + throw new NotUpdatable(); + + } + + public void updateRowId(int columnIndex, RowId x) throws SQLException { + throw new NotUpdatable(); + } + + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { + updateAsciiStream(findColumn(columnLabel), x); + } + + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { + updateAsciiStream(findColumn(columnLabel), x, length); + } + + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { + updateBinaryStream(findColumn(columnLabel), x); + } + + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { + updateBinaryStream(findColumn(columnLabel), x, length); + } + + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { + updateBlob(findColumn(columnLabel), inputStream); + } + + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { + updateBlob(findColumn(columnLabel), inputStream, length); + } + + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { + updateCharacterStream(findColumn(columnLabel), reader); + } + + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + updateCharacterStream(findColumn(columnLabel), reader, length); + } + + public void updateClob(String columnLabel, Reader reader) throws SQLException { + updateClob(findColumn(columnLabel), reader); + } + + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { + updateClob(findColumn(columnLabel), reader, length); + } + + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { + updateNCharacterStream(findColumn(columnLabel), reader); + + } + + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + updateNCharacterStream(findColumn(columnLabel), reader, length); + } + + + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + updateNClob(findColumn(columnLabel), reader); + + } + + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { + updateNClob(findColumn(columnLabel), reader, length); + } + + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + updateSQLXML(findColumn(columnLabel), xmlObject); + + } + + /** + * JDBC 4.0 Update a column with a character stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param length + * the length of the stream + * + * @exception SQLException + * if a database-access error occurs + */ + public synchronized void updateNCharacterStream(int columnIndex, + java.io.Reader x, int length) throws SQLException { + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call updateNCharacterStream() when field's character set isn't UTF-8"); + } + + if (!this.onInsertRow) { + if (!this.doingUpdates) { + this.doingUpdates = true; + syncUpdate(); + } + + ((com.mysql.jdbc.JDBC4PreparedStatement)this.updater).setNCharacterStream(columnIndex, x, length); + } else { + ((com.mysql.jdbc.JDBC4PreparedStatement)this.inserter).setNCharacterStream(columnIndex, x, length); + + if (x == null) { + this.thisRow.setColumnValue(columnIndex - 1, null); + } else { + this.thisRow.setColumnValue(columnIndex - 1, STREAM_DATA_MARKER); + } + } + } + + /** + * JDBC 4.0 Update a column with a character stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnName + * the name of the column + * @param reader + * the new column value + * @param length + * of the stream + * + * @exception SQLException + * if a database-access error occurs + */ + public synchronized void updateNCharacterStream(String columnName, + java.io.Reader reader, int length) throws SQLException { + updateNCharacterStream(findColumn(columnName), reader, length); + } + + /** + * @see ResultSet#updateNClob(int, NClob) + */ + public void updateNClob(int columnIndex, java.sql.NClob nClob) + throws SQLException { + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException("Can not call updateNClob() when field's character set isn't UTF-8"); + } + + if (nClob == null) { + updateNull(columnIndex); + } else { + updateNCharacterStream(columnIndex, nClob.getCharacterStream(), + (int) nClob.length()); + } + } + + /** + * @see ResultSet#updateClob(int, Clob) + */ + public void updateNClob(String columnName, java.sql.NClob nClob) + throws SQLException { + updateNClob(findColumn(columnName), nClob); + } + + /** + * JDBC 4.0 Update a column with NATIONAL CHARACTER. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public synchronized void updateNString(int columnIndex, String x) + throws SQLException { + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException("Can not call updateNString() when field's character set isn't UTF-8"); + } + + if (!this.onInsertRow) { + if (!this.doingUpdates) { + this.doingUpdates = true; + syncUpdate(); + } + + ((com.mysql.jdbc.JDBC4PreparedStatement)this.updater).setNString(columnIndex, x); + } else { + ((com.mysql.jdbc.JDBC4PreparedStatement)this.inserter).setNString(columnIndex, x); + + if (x == null) { + this.thisRow.setColumnValue(columnIndex - 1, null); + } else { + this.thisRow.setColumnValue(columnIndex - 1, StringUtils.getBytes(x, + this.charConverter, fieldEncoding, + this.connection.getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor())); + } + } + } + + /** + * JDBC 4.0 Update a column with NATIONAL CHARACTER. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public synchronized void updateNString(String columnName, String x) + throws SQLException { + updateNString(findColumn(columnName), x); + } + + public int getHoldability() throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * JDBC 4.0 Get a NCLOB column. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return an object representing a NCLOB + * + * @throws SQLException + * if an error occurs + */ + protected java.sql.NClob getNativeNClob(int columnIndex) + throws SQLException { + String stringVal = getStringForNClob(columnIndex); + + if (stringVal == null) { + return null; + } + + return getNClobFromString(stringVal, columnIndex); + } + + /** + * JDBC 4.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnIndex + * the column to get the value from + * + * @return the value in the column as a java.io.Reader. + * + * @throws SQLException + * if an error occurs + */ + public Reader getNCharacterStream(int columnIndex) throws SQLException { + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call getNCharacterStream() when field's charset isn't UTF-8"); + } + + return getCharacterStream(columnIndex); + } + + /** + * JDBC 4.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnName + * the column name to retrieve the value from + * + * @return the value as a java.io.Reader + * + * @throws SQLException + * if an error occurs + */ + public Reader getNCharacterStream(String columnName) throws SQLException { + return getNCharacterStream(findColumn(columnName)); + } + + /** + * JDBC 4.0 Get a NCLOB column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing a NCLOB + * + * @throws SQLException + * if an error occurs + */ + public NClob getNClob(int columnIndex) throws SQLException { + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call getNClob() when field's charset isn't UTF-8"); + } + + if (!this.isBinaryEncoded) { + String asString = getStringForNClob(columnIndex); + + if (asString == null) { + return null; + } + + return new com.mysql.jdbc.JDBC4NClob(asString, getExceptionInterceptor()); + } + + return getNativeNClob(columnIndex); + } + + /** + * JDBC 4.0 Get a NCLOB column. + * + * @param colName + * the column name + * + * @return an object representing a NCLOB + * + * @throws SQLException + * if an error occurs + */ + public NClob getNClob(String columnName) throws SQLException { + return getNClob(findColumn(columnName)); + } + + private final java.sql.NClob getNClobFromString(String stringVal, + int columnIndex) throws SQLException { + return new com.mysql.jdbc.JDBC4NClob(stringVal, getExceptionInterceptor()); + } + + /** + * JDBC 4.0 + * + * Get the value of a column in the current row as a Java String + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value, null for SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public String getNString(int columnIndex) throws SQLException { + String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet(); + + if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) { + throw new SQLException( + "Can not call getNString() when field's charset isn't UTF-8"); + } + + return getString(columnIndex); + } + + /** + * JDBC 4.0 + * + * The following routines simply convert the columnName into a columnIndex + * and then call the appropriate routine above. + * + * @param columnName + * is the SQL name of the column + * + * @return the column value + * + * @exception SQLException + * if a database access error occurs + */ + public String getNString(String columnName) throws SQLException { + return getNString(findColumn(columnName)); + } + + public RowId getRowId(int columnIndex) throws SQLException { + throw SQLError.notImplemented(); + } + + public RowId getRowId(String columnLabel) throws SQLException { + return getRowId(findColumn(columnLabel)); + } + + public SQLXML getSQLXML(int columnIndex) throws SQLException { + return new JDBC4MysqlSQLXML(this, columnIndex, getExceptionInterceptor()); + } + + public SQLXML getSQLXML(String columnLabel) throws SQLException { + return getSQLXML(findColumn(columnLabel)); + } + + private String getStringForNClob(int columnIndex) throws SQLException { + String asString = null; + + String forcedEncoding = "UTF-8"; + + try { + byte[] asBytes = null; + + if (!this.isBinaryEncoded) { + asBytes = getBytes(columnIndex); + } else { + asBytes = getNativeBytes(columnIndex, true); + } + + if (asBytes != null) { + asString = new String(asBytes, forcedEncoding); + } + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException("Unsupported character encoding " + + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return asString; + } + + public synchronized boolean isClosed() throws SQLException { + return this.isClosed; + } + + /** + * Returns true if this either implements the interface argument or is + * directly or indirectly a wrapper for an object that does. Returns false + * otherwise. If this implements the interface then return true, else if + * this is a wrapper then return the result of recursively calling + * isWrapperFor on the wrapped object. If this does not + * implement the interface and is not a wrapper, return false. This method + * should be implemented as a low-cost operation compared to + * unwrap so that callers can use this method to avoid + * expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument + * should succeed. + * + * @param interfaces + * a Class defining an interface. + * @return true if this implements the interface or directly or indirectly + * wraps an object that does. + * @throws java.sql.SQLException + * if an error occurs while determining whether this is a + * wrapper for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to + * non-standard methods, or standard methods not exposed by the proxy. The + * result may be either the object found to implement the interface or a + * proxy for that object. If the receiver implements the interface then that + * is the object. If the receiver is a wrapper and the wrapped object + * implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped + * object. If the receiver is not a wrapper and does not implement the + * interface, then an SQLException is thrown. + * + * @param iface + * A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the + * actual implementing object. + * @throws java.sql.SQLException + * If no object found that implements the interface + * @since 1.6 + */ + public T unwrap(java.lang.Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return iface.cast(this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LicenseConfiguration.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LicenseConfiguration.java (.../LicenseConfiguration.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LicenseConfiguration.java (.../LicenseConfiguration.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,29 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; - import java.util.Map; /** @@ -49,7 +47,7 @@ * @throws SQLException * if commercial license is required, but not found */ - static void checkLicenseType(Map serverVariables) throws SQLException { + static void checkLicenseType(Map serverVariables) throws SQLException { // This is a GPL build, so we don't check anything... } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalanceExceptionChecker.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalanceExceptionChecker.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalanceExceptionChecker.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + + +public interface LoadBalanceExceptionChecker extends Extension { + + /** + * Invoked to determine whether or a given SQLException should + * trigger a failover in a load-balanced deployment. + * + * The driver will not pass in a Connection instance when calling init(), but it + * will pass in the Properties, otherwise it acts like a normal Extension. + * + * One instance of a handler *per* JDBC connection instance will be created. If + * you need singleton-like behavior, you're on your own to provide it. + + * @param ex + * @return true if the exception should trigger failover. + */ + public boolean shouldExceptionTriggerFailover(SQLException ex); + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedAutoCommitInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedAutoCommitInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedAutoCommitInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,139 @@ +/* + Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + + + +/** + * @author tf221715 + * + */ +public class LoadBalancedAutoCommitInterceptor implements + StatementInterceptorV2 { + private int matchingAfterStatementCount = 0; + private int matchingAfterStatementThreshold = 0; + private String matchingAfterStatementRegex; + private ConnectionImpl conn; + private LoadBalancingConnectionProxy proxy = null; + + + + public void destroy() { + // do nothing here + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.StatementInterceptorV2#executeTopLevelOnly() + */ + public boolean executeTopLevelOnly() { + // always return false + return false; + } + + public void init(Connection connection, Properties props) throws SQLException { + this.conn = (ConnectionImpl) connection; + + String autoCommitSwapThresholdAsString = props.getProperty("loadBalanceAutoCommitStatementThreshold", + "0"); + try { + this.matchingAfterStatementThreshold = Integer.parseInt(autoCommitSwapThresholdAsString); + } catch (NumberFormatException nfe) { + // nothing here, being handled in LoadBalancingConnectionProxy. + } + String autoCommitSwapRegex = props.getProperty("loadBalanceAutoCommitStatementRegex",""); + if("".equals(autoCommitSwapRegex)){ + return; + } + this.matchingAfterStatementRegex = autoCommitSwapRegex; + + } + + /* (non-Javadoc) + * @see com.mysql.jdbc.StatementInterceptorV2#postProcess(java.lang.String, com.mysql.jdbc.Statement, com.mysql.jdbc.ResultSetInternalMethods, com.mysql.jdbc.Connection, int, boolean, boolean, java.sql.SQLException) + */ + public ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection, + int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, + SQLException statementException) throws SQLException { + + // don't care if auto-commit is not enabled + if(!this.conn.getAutoCommit()){ + this.matchingAfterStatementCount = 0; + // auto-commit is enabled: + } else { + + if(this.proxy == null && this.conn.isProxySet()){ + MySQLConnection lcl_proxy = this.conn.getLoadBalanceSafeProxy(); + while(lcl_proxy != null && !(lcl_proxy instanceof LoadBalancedMySQLConnection)){ + lcl_proxy = lcl_proxy.getLoadBalanceSafeProxy(); + } + if(lcl_proxy != null){ + this.proxy = ((LoadBalancedMySQLConnection) lcl_proxy).getProxy(); + } + + } + + if(this.proxy != null){ + // increment the match count if no regex specified, or if matches: + if(this.matchingAfterStatementRegex == null + || sql.matches(matchingAfterStatementRegex)){ + this.matchingAfterStatementCount++; + } + } + // trigger rebalance if count exceeds threshold: + if(this.matchingAfterStatementCount >= this.matchingAfterStatementThreshold){ + this.matchingAfterStatementCount = 0; + try{ + if(this.proxy != null){ + this.proxy.pickNewConnection(); + } + + } catch (SQLException e){ + // eat this exception, the auto-commit statement completed, but we + // could not rebalance for some reason. User may get exception + // when using connection next. + } + } + } + // always return the original result set. + return originalResultSet; + } + + + public ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException { + // we do nothing before execution, it's unsafe to swap servers at this point. + return null; + } + + + + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,34 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + +public interface LoadBalancedConnection extends MySQLConnection { + + public boolean addHost(String host) throws SQLException; + public void removeHost(String host) throws SQLException; + public void removeHostWhenNotInUse(String host) throws SQLException; + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedMySQLConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedMySQLConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancedMySQLConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,2711 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.CallableStatement; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Savepoint; +import java.sql.Statement; +import java.util.Calendar; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TimeZone; +import java.util.Timer; +import java.util.concurrent.Executor; + +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.profiler.ProfilerEventHandler; + +public class LoadBalancedMySQLConnection implements LoadBalancedConnection { + + protected LoadBalancingConnectionProxy proxy; + + public LoadBalancingConnectionProxy getProxy(){ + return this.proxy; + } + + protected MySQLConnection getActiveMySQLConnection() { + synchronized (this.proxy) { + return this.proxy.currentConn; + } + } + + public LoadBalancedMySQLConnection(LoadBalancingConnectionProxy proxy) { + this.proxy = proxy; + } + + public void abortInternal() throws SQLException { + getActiveMySQLConnection().abortInternal(); + } + + public void changeUser(String userName, String newPassword) + throws SQLException { + getActiveMySQLConnection().changeUser(userName, newPassword); + } + + public void checkClosed() throws SQLException { + getActiveMySQLConnection().checkClosed(); + } + + public void clearHasTriedMaster() { + getActiveMySQLConnection().clearHasTriedMaster(); + } + + public void clearWarnings() throws SQLException { + getActiveMySQLConnection().clearWarnings(); + } + + public PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return getActiveMySQLConnection().clientPrepareStatement(sql, + resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + return getActiveMySQLConnection().clientPrepareStatement(sql, + resultSetType, resultSetConcurrency); + } + + public PreparedStatement clientPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + return getActiveMySQLConnection().clientPrepareStatement(sql, + autoGenKeyIndex); + } + + public PreparedStatement clientPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + return getActiveMySQLConnection().clientPrepareStatement(sql, + autoGenKeyIndexes); + } + + public PreparedStatement clientPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + return getActiveMySQLConnection().clientPrepareStatement(sql, + autoGenKeyColNames); + } + + public PreparedStatement clientPrepareStatement(String sql) + throws SQLException { + return getActiveMySQLConnection().clientPrepareStatement(sql); + } + + public void close() throws SQLException { + getActiveMySQLConnection().close(); + } + + public void commit() throws SQLException { + getActiveMySQLConnection().commit(); + } + + public void createNewIO(boolean isForReconnect) throws SQLException { + getActiveMySQLConnection().createNewIO(isForReconnect); + } + + public Statement createStatement() throws SQLException { + return getActiveMySQLConnection().createStatement(); + } + + public Statement createStatement(int resultSetType, + int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return getActiveMySQLConnection().createStatement(resultSetType, + resultSetConcurrency, resultSetHoldability); + } + + public Statement createStatement(int resultSetType, int resultSetConcurrency) + throws SQLException { + return getActiveMySQLConnection().createStatement(resultSetType, + resultSetConcurrency); + } + + public void dumpTestcaseQuery(String query) { + getActiveMySQLConnection().dumpTestcaseQuery(query); + } + + public Connection duplicate() throws SQLException { + return getActiveMySQLConnection().duplicate(); + } + + public ResultSetInternalMethods execSQL(StatementImpl callingStatement, + String sql, int maxRows, Buffer packet, int resultSetType, + int resultSetConcurrency, boolean streamResults, String catalog, + Field[] cachedMetadata, boolean isBatch) throws SQLException { + return getActiveMySQLConnection().execSQL(callingStatement, sql, + maxRows, packet, resultSetType, resultSetConcurrency, + streamResults, catalog, cachedMetadata, isBatch); + } + + public ResultSetInternalMethods execSQL(StatementImpl callingStatement, + String sql, int maxRows, Buffer packet, int resultSetType, + int resultSetConcurrency, boolean streamResults, String catalog, + Field[] cachedMetadata) throws SQLException { + return getActiveMySQLConnection().execSQL(callingStatement, sql, + maxRows, packet, resultSetType, resultSetConcurrency, + streamResults, catalog, cachedMetadata); + } + + public String extractSqlFromPacket(String possibleSqlQuery, + Buffer queryPacket, int endOfQueryPacketPosition) + throws SQLException { + return getActiveMySQLConnection().extractSqlFromPacket( + possibleSqlQuery, queryPacket, endOfQueryPacketPosition); + } + + public String exposeAsXml() throws SQLException { + return getActiveMySQLConnection().exposeAsXml(); + } + + public boolean getAllowLoadLocalInfile() { + return getActiveMySQLConnection().getAllowLoadLocalInfile(); + } + + public boolean getAllowMultiQueries() { + return getActiveMySQLConnection().getAllowMultiQueries(); + } + + public boolean getAllowNanAndInf() { + return getActiveMySQLConnection().getAllowNanAndInf(); + } + + public boolean getAllowUrlInLocalInfile() { + return getActiveMySQLConnection().getAllowUrlInLocalInfile(); + } + + public boolean getAlwaysSendSetIsolation() { + return getActiveMySQLConnection().getAlwaysSendSetIsolation(); + } + + public boolean getAutoClosePStmtStreams() { + return getActiveMySQLConnection().getAutoClosePStmtStreams(); + } + + public boolean getAutoDeserialize() { + return getActiveMySQLConnection().getAutoDeserialize(); + } + + public boolean getAutoGenerateTestcaseScript() { + return getActiveMySQLConnection().getAutoGenerateTestcaseScript(); + } + + public boolean getAutoReconnectForPools() { + return getActiveMySQLConnection().getAutoReconnectForPools(); + } + + public boolean getAutoSlowLog() { + return getActiveMySQLConnection().getAutoSlowLog(); + } + + public int getBlobSendChunkSize() { + return getActiveMySQLConnection().getBlobSendChunkSize(); + } + + public boolean getBlobsAreStrings() { + return getActiveMySQLConnection().getBlobsAreStrings(); + } + + public boolean getCacheCallableStatements() { + return getActiveMySQLConnection().getCacheCallableStatements(); + } + + public boolean getCacheCallableStmts() { + return getActiveMySQLConnection().getCacheCallableStmts(); + } + + public boolean getCachePrepStmts() { + return getActiveMySQLConnection().getCachePrepStmts(); + } + + public boolean getCachePreparedStatements() { + return getActiveMySQLConnection().getCachePreparedStatements(); + } + + public boolean getCacheResultSetMetadata() { + return getActiveMySQLConnection().getCacheResultSetMetadata(); + } + + public boolean getCacheServerConfiguration() { + return getActiveMySQLConnection().getCacheServerConfiguration(); + } + + public int getCallableStatementCacheSize() { + return getActiveMySQLConnection().getCallableStatementCacheSize(); + } + + public int getCallableStmtCacheSize() { + return getActiveMySQLConnection().getCallableStmtCacheSize(); + } + + public boolean getCapitalizeTypeNames() { + return getActiveMySQLConnection().getCapitalizeTypeNames(); + } + + public String getCharacterSetResults() { + return getActiveMySQLConnection().getCharacterSetResults(); + } + + public String getClientCertificateKeyStorePassword() { + return getActiveMySQLConnection() + .getClientCertificateKeyStorePassword(); + } + + public String getClientCertificateKeyStoreType() { + return getActiveMySQLConnection().getClientCertificateKeyStoreType(); + } + + public String getClientCertificateKeyStoreUrl() { + return getActiveMySQLConnection().getClientCertificateKeyStoreUrl(); + } + + public String getClientInfoProvider() { + return getActiveMySQLConnection().getClientInfoProvider(); + } + + public String getClobCharacterEncoding() { + return getActiveMySQLConnection().getClobCharacterEncoding(); + } + + public boolean getClobberStreamingResults() { + return getActiveMySQLConnection().getClobberStreamingResults(); + } + + public boolean getCompensateOnDuplicateKeyUpdateCounts() { + return getActiveMySQLConnection() + .getCompensateOnDuplicateKeyUpdateCounts(); + } + + public int getConnectTimeout() { + return getActiveMySQLConnection().getConnectTimeout(); + } + + public String getConnectionCollation() { + return getActiveMySQLConnection().getConnectionCollation(); + } + + public String getConnectionLifecycleInterceptors() { + return getActiveMySQLConnection().getConnectionLifecycleInterceptors(); + } + + public boolean getContinueBatchOnError() { + return getActiveMySQLConnection().getContinueBatchOnError(); + } + + public boolean getCreateDatabaseIfNotExist() { + return getActiveMySQLConnection().getCreateDatabaseIfNotExist(); + } + + public int getDefaultFetchSize() { + return getActiveMySQLConnection().getDefaultFetchSize(); + } + + public boolean getDontTrackOpenResources() { + return getActiveMySQLConnection().getDontTrackOpenResources(); + } + + public boolean getDumpMetadataOnColumnNotFound() { + return getActiveMySQLConnection().getDumpMetadataOnColumnNotFound(); + } + + public boolean getDumpQueriesOnException() { + return getActiveMySQLConnection().getDumpQueriesOnException(); + } + + public boolean getDynamicCalendars() { + return getActiveMySQLConnection().getDynamicCalendars(); + } + + public boolean getElideSetAutoCommits() { + return getActiveMySQLConnection().getElideSetAutoCommits(); + } + + public boolean getEmptyStringsConvertToZero() { + return getActiveMySQLConnection().getEmptyStringsConvertToZero(); + } + + public boolean getEmulateLocators() { + return getActiveMySQLConnection().getEmulateLocators(); + } + + public boolean getEmulateUnsupportedPstmts() { + return getActiveMySQLConnection().getEmulateUnsupportedPstmts(); + } + + public boolean getEnablePacketDebug() { + return getActiveMySQLConnection().getEnablePacketDebug(); + } + + public boolean getEnableQueryTimeouts() { + return getActiveMySQLConnection().getEnableQueryTimeouts(); + } + + public String getEncoding() { + return getActiveMySQLConnection().getEncoding(); + } + + public String getExceptionInterceptors() { + return getActiveMySQLConnection().getExceptionInterceptors(); + } + + public boolean getExplainSlowQueries() { + return getActiveMySQLConnection().getExplainSlowQueries(); + } + + public boolean getFailOverReadOnly() { + return getActiveMySQLConnection().getFailOverReadOnly(); + } + + public boolean getFunctionsNeverReturnBlobs() { + return getActiveMySQLConnection().getFunctionsNeverReturnBlobs(); + } + + public boolean getGatherPerfMetrics() { + return getActiveMySQLConnection().getGatherPerfMetrics(); + } + + public boolean getGatherPerformanceMetrics() { + return getActiveMySQLConnection().getGatherPerformanceMetrics(); + } + + public boolean getGenerateSimpleParameterMetadata() { + return getActiveMySQLConnection().getGenerateSimpleParameterMetadata(); + } + + public boolean getIgnoreNonTxTables() { + return getActiveMySQLConnection().getIgnoreNonTxTables(); + } + + public boolean getIncludeInnodbStatusInDeadlockExceptions() { + return getActiveMySQLConnection() + .getIncludeInnodbStatusInDeadlockExceptions(); + } + + public int getInitialTimeout() { + return getActiveMySQLConnection().getInitialTimeout(); + } + + public boolean getInteractiveClient() { + return getActiveMySQLConnection().getInteractiveClient(); + } + + public boolean getIsInteractiveClient() { + return getActiveMySQLConnection().getIsInteractiveClient(); + } + + public boolean getJdbcCompliantTruncation() { + return getActiveMySQLConnection().getJdbcCompliantTruncation(); + } + + public boolean getJdbcCompliantTruncationForReads() { + return getActiveMySQLConnection().getJdbcCompliantTruncationForReads(); + } + + public String getLargeRowSizeThreshold() { + return getActiveMySQLConnection().getLargeRowSizeThreshold(); + } + + public int getLoadBalanceBlacklistTimeout() { + return getActiveMySQLConnection().getLoadBalanceBlacklistTimeout(); + } + + public int getLoadBalancePingTimeout() { + return getActiveMySQLConnection().getLoadBalancePingTimeout(); + } + + public String getLoadBalanceStrategy() { + return getActiveMySQLConnection().getLoadBalanceStrategy(); + } + + public boolean getLoadBalanceValidateConnectionOnSwapServer() { + return getActiveMySQLConnection() + .getLoadBalanceValidateConnectionOnSwapServer(); + } + + public String getLocalSocketAddress() { + return getActiveMySQLConnection().getLocalSocketAddress(); + } + + public int getLocatorFetchBufferSize() { + return getActiveMySQLConnection().getLocatorFetchBufferSize(); + } + + public boolean getLogSlowQueries() { + return getActiveMySQLConnection().getLogSlowQueries(); + } + + public boolean getLogXaCommands() { + return getActiveMySQLConnection().getLogXaCommands(); + } + + public String getLogger() { + return getActiveMySQLConnection().getLogger(); + } + + public String getLoggerClassName() { + return getActiveMySQLConnection().getLoggerClassName(); + } + + public boolean getMaintainTimeStats() { + return getActiveMySQLConnection().getMaintainTimeStats(); + } + + public int getMaxAllowedPacket() { + return getActiveMySQLConnection().getMaxAllowedPacket(); + } + + public int getMaxQuerySizeToLog() { + return getActiveMySQLConnection().getMaxQuerySizeToLog(); + } + + public int getMaxReconnects() { + return getActiveMySQLConnection().getMaxReconnects(); + } + + public int getMaxRows() { + return getActiveMySQLConnection().getMaxRows(); + } + + public int getMetadataCacheSize() { + return getActiveMySQLConnection().getMetadataCacheSize(); + } + + public int getNetTimeoutForStreamingResults() { + return getActiveMySQLConnection().getNetTimeoutForStreamingResults(); + } + + public boolean getNoAccessToProcedureBodies() { + return getActiveMySQLConnection().getNoAccessToProcedureBodies(); + } + + public boolean getNoDatetimeStringSync() { + return getActiveMySQLConnection().getNoDatetimeStringSync(); + } + + public boolean getNoTimezoneConversionForTimeType() { + return getActiveMySQLConnection().getNoTimezoneConversionForTimeType(); + } + + public boolean getNullCatalogMeansCurrent() { + return getActiveMySQLConnection().getNullCatalogMeansCurrent(); + } + + public boolean getNullNamePatternMatchesAll() { + return getActiveMySQLConnection().getNullNamePatternMatchesAll(); + } + + public boolean getOverrideSupportsIntegrityEnhancementFacility() { + return getActiveMySQLConnection() + .getOverrideSupportsIntegrityEnhancementFacility(); + } + + public int getPacketDebugBufferSize() { + return getActiveMySQLConnection().getPacketDebugBufferSize(); + } + + public boolean getPadCharsWithSpace() { + return getActiveMySQLConnection().getPadCharsWithSpace(); + } + + public boolean getParanoid() { + return getActiveMySQLConnection().getParanoid(); + } + + public String getPasswordCharacterEncoding() { + return getActiveMySQLConnection().getPasswordCharacterEncoding(); + } + + public boolean getPedantic() { + return getActiveMySQLConnection().getPedantic(); + } + + public boolean getPinGlobalTxToPhysicalConnection() { + return getActiveMySQLConnection().getPinGlobalTxToPhysicalConnection(); + } + + public boolean getPopulateInsertRowWithDefaultValues() { + return getActiveMySQLConnection() + .getPopulateInsertRowWithDefaultValues(); + } + + public int getPrepStmtCacheSize() { + return getActiveMySQLConnection().getPrepStmtCacheSize(); + } + + public int getPrepStmtCacheSqlLimit() { + return getActiveMySQLConnection().getPrepStmtCacheSqlLimit(); + } + + public int getPreparedStatementCacheSize() { + return getActiveMySQLConnection().getPreparedStatementCacheSize(); + } + + public int getPreparedStatementCacheSqlLimit() { + return getActiveMySQLConnection().getPreparedStatementCacheSqlLimit(); + } + + public boolean getProcessEscapeCodesForPrepStmts() { + return getActiveMySQLConnection().getProcessEscapeCodesForPrepStmts(); + } + + public boolean getProfileSQL() { + return getActiveMySQLConnection().getProfileSQL(); + } + + public boolean getProfileSql() { + return getActiveMySQLConnection().getProfileSql(); + } + + public String getProfilerEventHandler() { + return getActiveMySQLConnection().getProfilerEventHandler(); + } + + public String getPropertiesTransform() { + return getActiveMySQLConnection().getPropertiesTransform(); + } + + public int getQueriesBeforeRetryMaster() { + return getActiveMySQLConnection().getQueriesBeforeRetryMaster(); + } + + public boolean getQueryTimeoutKillsConnection() { + return getActiveMySQLConnection().getQueryTimeoutKillsConnection(); + } + + public boolean getReconnectAtTxEnd() { + return getActiveMySQLConnection().getReconnectAtTxEnd(); + } + + public boolean getRelaxAutoCommit() { + return getActiveMySQLConnection().getRelaxAutoCommit(); + } + + public int getReportMetricsIntervalMillis() { + return getActiveMySQLConnection().getReportMetricsIntervalMillis(); + } + + public boolean getRequireSSL() { + return getActiveMySQLConnection().getRequireSSL(); + } + + public String getResourceId() { + return getActiveMySQLConnection().getResourceId(); + } + + public int getResultSetSizeThreshold() { + return getActiveMySQLConnection().getResultSetSizeThreshold(); + } + + public boolean getRetainStatementAfterResultSetClose() { + return getActiveMySQLConnection() + .getRetainStatementAfterResultSetClose(); + } + + public int getRetriesAllDown() { + return getActiveMySQLConnection().getRetriesAllDown(); + } + + public boolean getRewriteBatchedStatements() { + return getActiveMySQLConnection().getRewriteBatchedStatements(); + } + + public boolean getRollbackOnPooledClose() { + return getActiveMySQLConnection().getRollbackOnPooledClose(); + } + + public boolean getRoundRobinLoadBalance() { + return getActiveMySQLConnection().getRoundRobinLoadBalance(); + } + + public boolean getRunningCTS13() { + return getActiveMySQLConnection().getRunningCTS13(); + } + + public int getSecondsBeforeRetryMaster() { + return getActiveMySQLConnection().getSecondsBeforeRetryMaster(); + } + + public int getSelfDestructOnPingMaxOperations() { + return getActiveMySQLConnection().getSelfDestructOnPingMaxOperations(); + } + + public int getSelfDestructOnPingSecondsLifetime() { + return getActiveMySQLConnection() + .getSelfDestructOnPingSecondsLifetime(); + } + + public String getServerTimezone() { + return getActiveMySQLConnection().getServerTimezone(); + } + + public String getSessionVariables() { + return getActiveMySQLConnection().getSessionVariables(); + } + + public int getSlowQueryThresholdMillis() { + return getActiveMySQLConnection().getSlowQueryThresholdMillis(); + } + + public long getSlowQueryThresholdNanos() { + return getActiveMySQLConnection().getSlowQueryThresholdNanos(); + } + + public String getSocketFactory() { + return getActiveMySQLConnection().getSocketFactory(); + } + + public String getSocketFactoryClassName() { + return getActiveMySQLConnection().getSocketFactoryClassName(); + } + + public int getSocketTimeout() { + return getActiveMySQLConnection().getSocketTimeout(); + } + + public String getStatementInterceptors() { + return getActiveMySQLConnection().getStatementInterceptors(); + } + + public boolean getStrictFloatingPoint() { + return getActiveMySQLConnection().getStrictFloatingPoint(); + } + + public boolean getStrictUpdates() { + return getActiveMySQLConnection().getStrictUpdates(); + } + + public boolean getTcpKeepAlive() { + return getActiveMySQLConnection().getTcpKeepAlive(); + } + + public boolean getTcpNoDelay() { + return getActiveMySQLConnection().getTcpNoDelay(); + } + + public int getTcpRcvBuf() { + return getActiveMySQLConnection().getTcpRcvBuf(); + } + + public int getTcpSndBuf() { + return getActiveMySQLConnection().getTcpSndBuf(); + } + + public int getTcpTrafficClass() { + return getActiveMySQLConnection().getTcpTrafficClass(); + } + + public boolean getTinyInt1isBit() { + return getActiveMySQLConnection().getTinyInt1isBit(); + } + + public boolean getTraceProtocol() { + return getActiveMySQLConnection().getTraceProtocol(); + } + + public boolean getTransformedBitIsBoolean() { + return getActiveMySQLConnection().getTransformedBitIsBoolean(); + } + + public boolean getTreatUtilDateAsTimestamp() { + return getActiveMySQLConnection().getTreatUtilDateAsTimestamp(); + } + + public String getTrustCertificateKeyStorePassword() { + return getActiveMySQLConnection().getTrustCertificateKeyStorePassword(); + } + + public String getTrustCertificateKeyStoreType() { + return getActiveMySQLConnection().getTrustCertificateKeyStoreType(); + } + + public String getTrustCertificateKeyStoreUrl() { + return getActiveMySQLConnection().getTrustCertificateKeyStoreUrl(); + } + + public boolean getUltraDevHack() { + return getActiveMySQLConnection().getUltraDevHack(); + } + + public boolean getUseAffectedRows() { + return getActiveMySQLConnection().getUseAffectedRows(); + } + + public boolean getUseBlobToStoreUTF8OutsideBMP() { + return getActiveMySQLConnection().getUseBlobToStoreUTF8OutsideBMP(); + } + + public boolean getUseColumnNamesInFindColumn() { + return getActiveMySQLConnection().getUseColumnNamesInFindColumn(); + } + + public boolean getUseCompression() { + return getActiveMySQLConnection().getUseCompression(); + } + + public String getUseConfigs() { + return getActiveMySQLConnection().getUseConfigs(); + } + + public boolean getUseCursorFetch() { + return getActiveMySQLConnection().getUseCursorFetch(); + } + + public boolean getUseDirectRowUnpack() { + return getActiveMySQLConnection().getUseDirectRowUnpack(); + } + + public boolean getUseDynamicCharsetInfo() { + return getActiveMySQLConnection().getUseDynamicCharsetInfo(); + } + + public boolean getUseFastDateParsing() { + return getActiveMySQLConnection().getUseFastDateParsing(); + } + + public boolean getUseFastIntParsing() { + return getActiveMySQLConnection().getUseFastIntParsing(); + } + + public boolean getUseGmtMillisForDatetimes() { + return getActiveMySQLConnection().getUseGmtMillisForDatetimes(); + } + + public boolean getUseHostsInPrivileges() { + return getActiveMySQLConnection().getUseHostsInPrivileges(); + } + + public boolean getUseInformationSchema() { + return getActiveMySQLConnection().getUseInformationSchema(); + } + + public boolean getUseJDBCCompliantTimezoneShift() { + return getActiveMySQLConnection().getUseJDBCCompliantTimezoneShift(); + } + + public boolean getUseJvmCharsetConverters() { + return getActiveMySQLConnection().getUseJvmCharsetConverters(); + } + + public boolean getUseLegacyDatetimeCode() { + return getActiveMySQLConnection().getUseLegacyDatetimeCode(); + } + + public boolean getUseLocalSessionState() { + return getActiveMySQLConnection().getUseLocalSessionState(); + } + + public boolean getUseLocalTransactionState() { + return getActiveMySQLConnection().getUseLocalTransactionState(); + } + + public boolean getUseNanosForElapsedTime() { + return getActiveMySQLConnection().getUseNanosForElapsedTime(); + } + + public boolean getUseOldAliasMetadataBehavior() { + return getActiveMySQLConnection().getUseOldAliasMetadataBehavior(); + } + + public boolean getUseOldUTF8Behavior() { + return getActiveMySQLConnection().getUseOldUTF8Behavior(); + } + + public boolean getUseOnlyServerErrorMessages() { + return getActiveMySQLConnection().getUseOnlyServerErrorMessages(); + } + + public boolean getUseReadAheadInput() { + return getActiveMySQLConnection().getUseReadAheadInput(); + } + + public boolean getUseSSL() { + return getActiveMySQLConnection().getUseSSL(); + } + + public boolean getUseSSPSCompatibleTimezoneShift() { + return getActiveMySQLConnection().getUseSSPSCompatibleTimezoneShift(); + } + + public boolean getUseServerPrepStmts() { + return getActiveMySQLConnection().getUseServerPrepStmts(); + } + + public boolean getUseServerPreparedStmts() { + return getActiveMySQLConnection().getUseServerPreparedStmts(); + } + + public boolean getUseSqlStateCodes() { + return getActiveMySQLConnection().getUseSqlStateCodes(); + } + + public boolean getUseStreamLengthsInPrepStmts() { + return getActiveMySQLConnection().getUseStreamLengthsInPrepStmts(); + } + + public boolean getUseTimezone() { + return getActiveMySQLConnection().getUseTimezone(); + } + + public boolean getUseUltraDevWorkAround() { + return getActiveMySQLConnection().getUseUltraDevWorkAround(); + } + + public boolean getUseUnbufferedInput() { + return getActiveMySQLConnection().getUseUnbufferedInput(); + } + + public boolean getUseUnicode() { + return getActiveMySQLConnection().getUseUnicode(); + } + + public boolean getUseUsageAdvisor() { + return getActiveMySQLConnection().getUseUsageAdvisor(); + } + + public String getUtf8OutsideBmpExcludedColumnNamePattern() { + return getActiveMySQLConnection() + .getUtf8OutsideBmpExcludedColumnNamePattern(); + } + + public String getUtf8OutsideBmpIncludedColumnNamePattern() { + return getActiveMySQLConnection() + .getUtf8OutsideBmpIncludedColumnNamePattern(); + } + + public boolean getVerifyServerCertificate() { + return getActiveMySQLConnection().getVerifyServerCertificate(); + } + + public boolean getYearIsDateType() { + return getActiveMySQLConnection().getYearIsDateType(); + } + + public String getZeroDateTimeBehavior() { + return getActiveMySQLConnection().getZeroDateTimeBehavior(); + } + + public void setAllowLoadLocalInfile(boolean property) { + getActiveMySQLConnection().setAllowLoadLocalInfile(property); + } + + public void setAllowMultiQueries(boolean property) { + getActiveMySQLConnection().setAllowMultiQueries(property); + } + + public void setAllowNanAndInf(boolean flag) { + getActiveMySQLConnection().setAllowNanAndInf(flag); + } + + public void setAllowUrlInLocalInfile(boolean flag) { + getActiveMySQLConnection().setAllowUrlInLocalInfile(flag); + } + + public void setAlwaysSendSetIsolation(boolean flag) { + getActiveMySQLConnection().setAlwaysSendSetIsolation(flag); + } + + public void setAutoClosePStmtStreams(boolean flag) { + getActiveMySQLConnection().setAutoClosePStmtStreams(flag); + } + + public void setAutoDeserialize(boolean flag) { + getActiveMySQLConnection().setAutoDeserialize(flag); + } + + public void setAutoGenerateTestcaseScript(boolean flag) { + getActiveMySQLConnection().setAutoGenerateTestcaseScript(flag); + } + + public void setAutoReconnect(boolean flag) { + getActiveMySQLConnection().setAutoReconnect(flag); + } + + public void setAutoReconnectForConnectionPools(boolean property) { + getActiveMySQLConnection().setAutoReconnectForConnectionPools(property); + } + + public void setAutoReconnectForPools(boolean flag) { + getActiveMySQLConnection().setAutoReconnectForPools(flag); + } + + public void setAutoSlowLog(boolean flag) { + getActiveMySQLConnection().setAutoSlowLog(flag); + } + + public void setBlobSendChunkSize(String value) throws SQLException { + getActiveMySQLConnection().setBlobSendChunkSize(value); + } + + public void setBlobsAreStrings(boolean flag) { + getActiveMySQLConnection().setBlobsAreStrings(flag); + } + + public void setCacheCallableStatements(boolean flag) { + getActiveMySQLConnection().setCacheCallableStatements(flag); + } + + public void setCacheCallableStmts(boolean flag) { + getActiveMySQLConnection().setCacheCallableStmts(flag); + } + + public void setCachePrepStmts(boolean flag) { + getActiveMySQLConnection().setCachePrepStmts(flag); + } + + public void setCachePreparedStatements(boolean flag) { + getActiveMySQLConnection().setCachePreparedStatements(flag); + } + + public void setCacheResultSetMetadata(boolean property) { + getActiveMySQLConnection().setCacheResultSetMetadata(property); + } + + public void setCacheServerConfiguration(boolean flag) { + getActiveMySQLConnection().setCacheServerConfiguration(flag); + } + + public void setCallableStatementCacheSize(int size) throws SQLException { + getActiveMySQLConnection().setCallableStatementCacheSize(size); + } + + public void setCallableStmtCacheSize(int cacheSize) throws SQLException { + getActiveMySQLConnection().setCallableStmtCacheSize(cacheSize); + } + + public void setCapitalizeDBMDTypes(boolean property) { + getActiveMySQLConnection().setCapitalizeDBMDTypes(property); + } + + public void setCapitalizeTypeNames(boolean flag) { + getActiveMySQLConnection().setCapitalizeTypeNames(flag); + } + + public void setCharacterEncoding(String encoding) { + getActiveMySQLConnection().setCharacterEncoding(encoding); + } + + public void setCharacterSetResults(String characterSet) { + getActiveMySQLConnection().setCharacterSetResults(characterSet); + } + + public void setClientCertificateKeyStorePassword(String value) { + getActiveMySQLConnection().setClientCertificateKeyStorePassword(value); + } + + public void setClientCertificateKeyStoreType(String value) { + getActiveMySQLConnection().setClientCertificateKeyStoreType(value); + } + + public void setClientCertificateKeyStoreUrl(String value) { + getActiveMySQLConnection().setClientCertificateKeyStoreUrl(value); + } + + public void setClientInfoProvider(String classname) { + getActiveMySQLConnection().setClientInfoProvider(classname); + } + + public void setClobCharacterEncoding(String encoding) { + getActiveMySQLConnection().setClobCharacterEncoding(encoding); + } + + public void setClobberStreamingResults(boolean flag) { + getActiveMySQLConnection().setClobberStreamingResults(flag); + } + + public void setCompensateOnDuplicateKeyUpdateCounts(boolean flag) { + getActiveMySQLConnection() + .setCompensateOnDuplicateKeyUpdateCounts(flag); + } + + public void setConnectTimeout(int timeoutMs) throws SQLException { + getActiveMySQLConnection().setConnectTimeout(timeoutMs); + } + + public void setConnectionCollation(String collation) { + getActiveMySQLConnection().setConnectionCollation(collation); + } + + public void setConnectionLifecycleInterceptors(String interceptors) { + getActiveMySQLConnection().setConnectionLifecycleInterceptors( + interceptors); + } + + public void setContinueBatchOnError(boolean property) { + getActiveMySQLConnection().setContinueBatchOnError(property); + } + + public void setCreateDatabaseIfNotExist(boolean flag) { + getActiveMySQLConnection().setCreateDatabaseIfNotExist(flag); + } + + public void setDefaultFetchSize(int n) throws SQLException { + getActiveMySQLConnection().setDefaultFetchSize(n); + } + + public void setDetectServerPreparedStmts(boolean property) { + getActiveMySQLConnection().setDetectServerPreparedStmts(property); + } + + public void setDontTrackOpenResources(boolean flag) { + getActiveMySQLConnection().setDontTrackOpenResources(flag); + } + + public void setDumpMetadataOnColumnNotFound(boolean flag) { + getActiveMySQLConnection().setDumpMetadataOnColumnNotFound(flag); + } + + public void setDumpQueriesOnException(boolean flag) { + getActiveMySQLConnection().setDumpQueriesOnException(flag); + } + + public void setDynamicCalendars(boolean flag) { + getActiveMySQLConnection().setDynamicCalendars(flag); + } + + public void setElideSetAutoCommits(boolean flag) { + getActiveMySQLConnection().setElideSetAutoCommits(flag); + } + + public void setEmptyStringsConvertToZero(boolean flag) { + getActiveMySQLConnection().setEmptyStringsConvertToZero(flag); + } + + public void setEmulateLocators(boolean property) { + getActiveMySQLConnection().setEmulateLocators(property); + } + + public void setEmulateUnsupportedPstmts(boolean flag) { + getActiveMySQLConnection().setEmulateUnsupportedPstmts(flag); + } + + public void setEnablePacketDebug(boolean flag) { + getActiveMySQLConnection().setEnablePacketDebug(flag); + } + + public void setEnableQueryTimeouts(boolean flag) { + getActiveMySQLConnection().setEnableQueryTimeouts(flag); + } + + public void setEncoding(String property) { + getActiveMySQLConnection().setEncoding(property); + } + + public void setExceptionInterceptors(String exceptionInterceptors) { + getActiveMySQLConnection().setExceptionInterceptors( + exceptionInterceptors); + } + + public void setExplainSlowQueries(boolean flag) { + getActiveMySQLConnection().setExplainSlowQueries(flag); + } + + public void setFailOverReadOnly(boolean flag) { + getActiveMySQLConnection().setFailOverReadOnly(flag); + } + + public void setFunctionsNeverReturnBlobs(boolean flag) { + getActiveMySQLConnection().setFunctionsNeverReturnBlobs(flag); + } + + public void setGatherPerfMetrics(boolean flag) { + getActiveMySQLConnection().setGatherPerfMetrics(flag); + } + + public void setGatherPerformanceMetrics(boolean flag) { + getActiveMySQLConnection().setGatherPerformanceMetrics(flag); + } + + public void setGenerateSimpleParameterMetadata(boolean flag) { + getActiveMySQLConnection().setGenerateSimpleParameterMetadata(flag); + } + + public void setHoldResultsOpenOverStatementClose(boolean flag) { + getActiveMySQLConnection().setHoldResultsOpenOverStatementClose(flag); + } + + public void setIgnoreNonTxTables(boolean property) { + getActiveMySQLConnection().setIgnoreNonTxTables(property); + } + + public void setIncludeInnodbStatusInDeadlockExceptions(boolean flag) { + getActiveMySQLConnection().setIncludeInnodbStatusInDeadlockExceptions( + flag); + } + + public void setInitialTimeout(int property) throws SQLException { + getActiveMySQLConnection().setInitialTimeout(property); + } + + public void setInteractiveClient(boolean property) { + getActiveMySQLConnection().setInteractiveClient(property); + } + + public void setIsInteractiveClient(boolean property) { + getActiveMySQLConnection().setIsInteractiveClient(property); + } + + public void setJdbcCompliantTruncation(boolean flag) { + getActiveMySQLConnection().setJdbcCompliantTruncation(flag); + } + + public void setJdbcCompliantTruncationForReads( + boolean jdbcCompliantTruncationForReads) { + getActiveMySQLConnection().setJdbcCompliantTruncationForReads( + jdbcCompliantTruncationForReads); + } + + public void setLargeRowSizeThreshold(String value) throws SQLException { + getActiveMySQLConnection().setLargeRowSizeThreshold(value); + } + + public void setLoadBalanceBlacklistTimeout(int loadBalanceBlacklistTimeout) throws SQLException { + getActiveMySQLConnection().setLoadBalanceBlacklistTimeout( + loadBalanceBlacklistTimeout); + } + + public void setLoadBalancePingTimeout(int loadBalancePingTimeout) throws SQLException { + getActiveMySQLConnection().setLoadBalancePingTimeout( + loadBalancePingTimeout); + } + + public void setLoadBalanceStrategy(String strategy) { + getActiveMySQLConnection().setLoadBalanceStrategy(strategy); + } + + public void setLoadBalanceValidateConnectionOnSwapServer( + boolean loadBalanceValidateConnectionOnSwapServer) { + + getActiveMySQLConnection() + .setLoadBalanceValidateConnectionOnSwapServer( + loadBalanceValidateConnectionOnSwapServer); + } + + public void setLocalSocketAddress(String address) { + + getActiveMySQLConnection().setLocalSocketAddress(address); + } + + public void setLocatorFetchBufferSize(String value) throws SQLException { + + getActiveMySQLConnection().setLocatorFetchBufferSize(value); + } + + public void setLogSlowQueries(boolean flag) { + + getActiveMySQLConnection().setLogSlowQueries(flag); + } + + public void setLogXaCommands(boolean flag) { + + getActiveMySQLConnection().setLogXaCommands(flag); + } + + public void setLogger(String property) { + + getActiveMySQLConnection().setLogger(property); + } + + public void setLoggerClassName(String className) { + + getActiveMySQLConnection().setLoggerClassName(className); + } + + public void setMaintainTimeStats(boolean flag) { + + getActiveMySQLConnection().setMaintainTimeStats(flag); + } + + public void setMaxQuerySizeToLog(int sizeInBytes) throws SQLException { + + getActiveMySQLConnection().setMaxQuerySizeToLog(sizeInBytes); + } + + public void setMaxReconnects(int property) throws SQLException { + + getActiveMySQLConnection().setMaxReconnects(property); + } + + public void setMaxRows(int property) throws SQLException { + + getActiveMySQLConnection().setMaxRows(property); + } + + public void setMetadataCacheSize(int value) throws SQLException { + + getActiveMySQLConnection().setMetadataCacheSize(value); + } + + public void setNetTimeoutForStreamingResults(int value) throws SQLException { + + getActiveMySQLConnection().setNetTimeoutForStreamingResults(value); + } + + public void setNoAccessToProcedureBodies(boolean flag) { + + getActiveMySQLConnection().setNoAccessToProcedureBodies(flag); + } + + public void setNoDatetimeStringSync(boolean flag) { + + getActiveMySQLConnection().setNoDatetimeStringSync(flag); + } + + public void setNoTimezoneConversionForTimeType(boolean flag) { + + getActiveMySQLConnection().setNoTimezoneConversionForTimeType(flag); + } + + public void setNullCatalogMeansCurrent(boolean value) { + + getActiveMySQLConnection().setNullCatalogMeansCurrent(value); + } + + public void setNullNamePatternMatchesAll(boolean value) { + + getActiveMySQLConnection().setNullNamePatternMatchesAll(value); + } + + public void setOverrideSupportsIntegrityEnhancementFacility(boolean flag) { + + getActiveMySQLConnection() + .setOverrideSupportsIntegrityEnhancementFacility(flag); + } + + public void setPacketDebugBufferSize(int size) throws SQLException { + + getActiveMySQLConnection().setPacketDebugBufferSize(size); + } + + public void setPadCharsWithSpace(boolean flag) { + + getActiveMySQLConnection().setPadCharsWithSpace(flag); + } + + public void setParanoid(boolean property) { + + getActiveMySQLConnection().setParanoid(property); + } + + public void setPasswordCharacterEncoding(String characterSet) { + + getActiveMySQLConnection().setPasswordCharacterEncoding(characterSet); + } + + public void setPedantic(boolean property) { + + getActiveMySQLConnection().setPedantic(property); + } + + public void setPinGlobalTxToPhysicalConnection(boolean flag) { + + getActiveMySQLConnection().setPinGlobalTxToPhysicalConnection(flag); + } + + public void setPopulateInsertRowWithDefaultValues(boolean flag) { + + getActiveMySQLConnection().setPopulateInsertRowWithDefaultValues(flag); + } + + public void setPrepStmtCacheSize(int cacheSize) throws SQLException { + + getActiveMySQLConnection().setPrepStmtCacheSize(cacheSize); + } + + public void setPrepStmtCacheSqlLimit(int sqlLimit) throws SQLException { + + getActiveMySQLConnection().setPrepStmtCacheSqlLimit(sqlLimit); + } + + public void setPreparedStatementCacheSize(int cacheSize) throws SQLException { + + getActiveMySQLConnection().setPreparedStatementCacheSize(cacheSize); + } + + public void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) throws SQLException { + + getActiveMySQLConnection().setPreparedStatementCacheSqlLimit( + cacheSqlLimit); + } + + public void setProcessEscapeCodesForPrepStmts(boolean flag) { + + getActiveMySQLConnection().setProcessEscapeCodesForPrepStmts(flag); + } + + public void setProfileSQL(boolean flag) { + + getActiveMySQLConnection().setProfileSQL(flag); + } + + public void setProfileSql(boolean property) { + + getActiveMySQLConnection().setProfileSql(property); + } + + public void setProfilerEventHandler(String handler) { + + getActiveMySQLConnection().setProfilerEventHandler(handler); + } + + public void setPropertiesTransform(String value) { + + getActiveMySQLConnection().setPropertiesTransform(value); + } + + public void setQueriesBeforeRetryMaster(int property) throws SQLException { + + getActiveMySQLConnection().setQueriesBeforeRetryMaster(property); + } + + public void setQueryTimeoutKillsConnection( + boolean queryTimeoutKillsConnection) { + + getActiveMySQLConnection().setQueryTimeoutKillsConnection( + queryTimeoutKillsConnection); + } + + public void setReconnectAtTxEnd(boolean property) { + + getActiveMySQLConnection().setReconnectAtTxEnd(property); + } + + public void setRelaxAutoCommit(boolean property) { + + getActiveMySQLConnection().setRelaxAutoCommit(property); + } + + public void setReportMetricsIntervalMillis(int millis) throws SQLException { + + getActiveMySQLConnection().setReportMetricsIntervalMillis(millis); + } + + public void setRequireSSL(boolean property) { + + getActiveMySQLConnection().setRequireSSL(property); + } + + public void setResourceId(String resourceId) { + + getActiveMySQLConnection().setResourceId(resourceId); + } + + public void setResultSetSizeThreshold(int threshold) throws SQLException { + + getActiveMySQLConnection().setResultSetSizeThreshold(threshold); + } + + public void setRetainStatementAfterResultSetClose(boolean flag) { + + getActiveMySQLConnection().setRetainStatementAfterResultSetClose(flag); + } + + public void setRetriesAllDown(int retriesAllDown) throws SQLException { + + getActiveMySQLConnection().setRetriesAllDown(retriesAllDown); + } + + public void setRewriteBatchedStatements(boolean flag) { + + getActiveMySQLConnection().setRewriteBatchedStatements(flag); + } + + public void setRollbackOnPooledClose(boolean flag) { + + getActiveMySQLConnection().setRollbackOnPooledClose(flag); + } + + public void setRoundRobinLoadBalance(boolean flag) { + + getActiveMySQLConnection().setRoundRobinLoadBalance(flag); + } + + public void setRunningCTS13(boolean flag) { + + getActiveMySQLConnection().setRunningCTS13(flag); + } + + public void setSecondsBeforeRetryMaster(int property) throws SQLException { + + getActiveMySQLConnection().setSecondsBeforeRetryMaster(property); + } + + public void setSelfDestructOnPingMaxOperations(int maxOperations) throws SQLException { + + getActiveMySQLConnection().setSelfDestructOnPingMaxOperations( + maxOperations); + } + + public void setSelfDestructOnPingSecondsLifetime(int seconds) throws SQLException { + + getActiveMySQLConnection() + .setSelfDestructOnPingSecondsLifetime(seconds); + } + + public void setServerTimezone(String property) { + + getActiveMySQLConnection().setServerTimezone(property); + } + + public void setSessionVariables(String variables) { + + getActiveMySQLConnection().setSessionVariables(variables); + } + + public void setSlowQueryThresholdMillis(int millis) throws SQLException { + + getActiveMySQLConnection().setSlowQueryThresholdMillis(millis); + } + + public void setSlowQueryThresholdNanos(long nanos) throws SQLException { + + getActiveMySQLConnection().setSlowQueryThresholdNanos(nanos); + } + + public void setSocketFactory(String name) { + + getActiveMySQLConnection().setSocketFactory(name); + } + + public void setSocketFactoryClassName(String property) { + + getActiveMySQLConnection().setSocketFactoryClassName(property); + } + + public void setSocketTimeout(int property) throws SQLException { + + getActiveMySQLConnection().setSocketTimeout(property); + } + + public void setStatementInterceptors(String value) { + + getActiveMySQLConnection().setStatementInterceptors(value); + } + + public void setStrictFloatingPoint(boolean property) { + + getActiveMySQLConnection().setStrictFloatingPoint(property); + } + + public void setStrictUpdates(boolean property) { + + getActiveMySQLConnection().setStrictUpdates(property); + } + + public void setTcpKeepAlive(boolean flag) { + + getActiveMySQLConnection().setTcpKeepAlive(flag); + } + + public void setTcpNoDelay(boolean flag) { + + getActiveMySQLConnection().setTcpNoDelay(flag); + } + + public void setTcpRcvBuf(int bufSize) throws SQLException { + + getActiveMySQLConnection().setTcpRcvBuf(bufSize); + } + + public void setTcpSndBuf(int bufSize) throws SQLException { + + getActiveMySQLConnection().setTcpSndBuf(bufSize); + } + + public void setTcpTrafficClass(int classFlags) throws SQLException { + + getActiveMySQLConnection().setTcpTrafficClass(classFlags); + } + + public void setTinyInt1isBit(boolean flag) { + + getActiveMySQLConnection().setTinyInt1isBit(flag); + } + + public void setTraceProtocol(boolean flag) { + + getActiveMySQLConnection().setTraceProtocol(flag); + } + + public void setTransformedBitIsBoolean(boolean flag) { + + getActiveMySQLConnection().setTransformedBitIsBoolean(flag); + } + + public void setTreatUtilDateAsTimestamp(boolean flag) { + + getActiveMySQLConnection().setTreatUtilDateAsTimestamp(flag); + } + + public void setTrustCertificateKeyStorePassword(String value) { + + getActiveMySQLConnection().setTrustCertificateKeyStorePassword(value); + } + + public void setTrustCertificateKeyStoreType(String value) { + + getActiveMySQLConnection().setTrustCertificateKeyStoreType(value); + } + + public void setTrustCertificateKeyStoreUrl(String value) { + + getActiveMySQLConnection().setTrustCertificateKeyStoreUrl(value); + } + + public void setUltraDevHack(boolean flag) { + + getActiveMySQLConnection().setUltraDevHack(flag); + } + + public void setUseAffectedRows(boolean flag) { + + getActiveMySQLConnection().setUseAffectedRows(flag); + } + + public void setUseBlobToStoreUTF8OutsideBMP(boolean flag) { + + getActiveMySQLConnection().setUseBlobToStoreUTF8OutsideBMP(flag); + } + + public void setUseColumnNamesInFindColumn(boolean flag) { + + getActiveMySQLConnection().setUseColumnNamesInFindColumn(flag); + } + + public void setUseCompression(boolean property) { + + getActiveMySQLConnection().setUseCompression(property); + } + + public void setUseConfigs(String configs) { + + getActiveMySQLConnection().setUseConfigs(configs); + } + + public void setUseCursorFetch(boolean flag) { + + getActiveMySQLConnection().setUseCursorFetch(flag); + } + + public void setUseDirectRowUnpack(boolean flag) { + + getActiveMySQLConnection().setUseDirectRowUnpack(flag); + } + + public void setUseDynamicCharsetInfo(boolean flag) { + + getActiveMySQLConnection().setUseDynamicCharsetInfo(flag); + } + + public void setUseFastDateParsing(boolean flag) { + + getActiveMySQLConnection().setUseFastDateParsing(flag); + } + + public void setUseFastIntParsing(boolean flag) { + + getActiveMySQLConnection().setUseFastIntParsing(flag); + } + + public void setUseGmtMillisForDatetimes(boolean flag) { + + getActiveMySQLConnection().setUseGmtMillisForDatetimes(flag); + } + + public void setUseHostsInPrivileges(boolean property) { + + getActiveMySQLConnection().setUseHostsInPrivileges(property); + } + + public void setUseInformationSchema(boolean flag) { + + getActiveMySQLConnection().setUseInformationSchema(flag); + } + + public void setUseJDBCCompliantTimezoneShift(boolean flag) { + + getActiveMySQLConnection().setUseJDBCCompliantTimezoneShift(flag); + } + + public void setUseJvmCharsetConverters(boolean flag) { + + getActiveMySQLConnection().setUseJvmCharsetConverters(flag); + } + + public void setUseLegacyDatetimeCode(boolean flag) { + + getActiveMySQLConnection().setUseLegacyDatetimeCode(flag); + } + + public void setUseLocalSessionState(boolean flag) { + + getActiveMySQLConnection().setUseLocalSessionState(flag); + } + + public void setUseLocalTransactionState(boolean flag) { + + getActiveMySQLConnection().setUseLocalTransactionState(flag); + } + + public void setUseNanosForElapsedTime(boolean flag) { + + getActiveMySQLConnection().setUseNanosForElapsedTime(flag); + } + + public void setUseOldAliasMetadataBehavior(boolean flag) { + + getActiveMySQLConnection().setUseOldAliasMetadataBehavior(flag); + } + + public void setUseOldUTF8Behavior(boolean flag) { + + getActiveMySQLConnection().setUseOldUTF8Behavior(flag); + } + + public void setUseOnlyServerErrorMessages(boolean flag) { + + getActiveMySQLConnection().setUseOnlyServerErrorMessages(flag); + } + + public void setUseReadAheadInput(boolean flag) { + + getActiveMySQLConnection().setUseReadAheadInput(flag); + } + + public void setUseSSL(boolean property) { + + getActiveMySQLConnection().setUseSSL(property); + } + + public void setUseSSPSCompatibleTimezoneShift(boolean flag) { + + getActiveMySQLConnection().setUseSSPSCompatibleTimezoneShift(flag); + } + + public void setUseServerPrepStmts(boolean flag) { + + getActiveMySQLConnection().setUseServerPrepStmts(flag); + } + + public void setUseServerPreparedStmts(boolean flag) { + + getActiveMySQLConnection().setUseServerPreparedStmts(flag); + } + + public void setUseSqlStateCodes(boolean flag) { + + getActiveMySQLConnection().setUseSqlStateCodes(flag); + } + + public void setUseStreamLengthsInPrepStmts(boolean property) { + + getActiveMySQLConnection().setUseStreamLengthsInPrepStmts(property); + } + + public void setUseTimezone(boolean property) { + + getActiveMySQLConnection().setUseTimezone(property); + } + + public void setUseUltraDevWorkAround(boolean property) { + + getActiveMySQLConnection().setUseUltraDevWorkAround(property); + } + + public void setUseUnbufferedInput(boolean flag) { + + getActiveMySQLConnection().setUseUnbufferedInput(flag); + } + + public void setUseUnicode(boolean flag) { + + getActiveMySQLConnection().setUseUnicode(flag); + } + + public void setUseUsageAdvisor(boolean useUsageAdvisorFlag) { + + getActiveMySQLConnection().setUseUsageAdvisor(useUsageAdvisorFlag); + } + + public void setUtf8OutsideBmpExcludedColumnNamePattern(String regexPattern) { + + getActiveMySQLConnection().setUtf8OutsideBmpExcludedColumnNamePattern( + regexPattern); + } + + public void setUtf8OutsideBmpIncludedColumnNamePattern(String regexPattern) { + + getActiveMySQLConnection().setUtf8OutsideBmpIncludedColumnNamePattern( + regexPattern); + } + + public void setVerifyServerCertificate(boolean flag) { + + getActiveMySQLConnection().setVerifyServerCertificate(flag); + } + + public void setYearIsDateType(boolean flag) { + + getActiveMySQLConnection().setYearIsDateType(flag); + } + + public void setZeroDateTimeBehavior(String behavior) { + + getActiveMySQLConnection().setZeroDateTimeBehavior(behavior); + } + + public boolean useUnbufferedInput() { + + return getActiveMySQLConnection().useUnbufferedInput(); + } + + public StringBuffer generateConnectionCommentBlock(StringBuffer buf) { + + return getActiveMySQLConnection().generateConnectionCommentBlock(buf); + } + + public int getActiveStatementCount() { + + return getActiveMySQLConnection().getActiveStatementCount(); + } + + public boolean getAutoCommit() throws SQLException { + + return getActiveMySQLConnection().getAutoCommit(); + } + + public int getAutoIncrementIncrement() { + + return getActiveMySQLConnection().getAutoIncrementIncrement(); + } + + public CachedResultSetMetaData getCachedMetaData(String sql) { + + return getActiveMySQLConnection().getCachedMetaData(sql); + } + + public Calendar getCalendarInstanceForSessionOrNew() { + + return getActiveMySQLConnection().getCalendarInstanceForSessionOrNew(); + } + + public Timer getCancelTimer() { + + return getActiveMySQLConnection().getCancelTimer(); + } + + public String getCatalog() throws SQLException { + + return getActiveMySQLConnection().getCatalog(); + } + + public String getCharacterSetMetadata() { + + return getActiveMySQLConnection().getCharacterSetMetadata(); + } + + public SingleByteCharsetConverter getCharsetConverter( + String javaEncodingName) throws SQLException { + + return getActiveMySQLConnection().getCharsetConverter(javaEncodingName); + } + + public String getCharsetNameForIndex(int charsetIndex) throws SQLException { + + return getActiveMySQLConnection().getCharsetNameForIndex(charsetIndex); + } + + public TimeZone getDefaultTimeZone() { + + return getActiveMySQLConnection().getDefaultTimeZone(); + } + + public String getErrorMessageEncoding() { + + return getActiveMySQLConnection().getErrorMessageEncoding(); + } + + public ExceptionInterceptor getExceptionInterceptor() { + + return getActiveMySQLConnection().getExceptionInterceptor(); + } + + public int getHoldability() throws SQLException { + + return getActiveMySQLConnection().getHoldability(); + } + + public String getHost() { + + return getActiveMySQLConnection().getHost(); + } + + public long getId() { + + return getActiveMySQLConnection().getId(); + } + + public long getIdleFor() { + + return getActiveMySQLConnection().getIdleFor(); + } + + public MysqlIO getIO() throws SQLException { + + return getActiveMySQLConnection().getIO(); + } + + public MySQLConnection getLoadBalanceSafeProxy() { + + return getActiveMySQLConnection().getLoadBalanceSafeProxy(); + } + + public Log getLog() throws SQLException { + + return getActiveMySQLConnection().getLog(); + } + + public int getMaxBytesPerChar(String javaCharsetName) throws SQLException { + + return getActiveMySQLConnection().getMaxBytesPerChar(javaCharsetName); + } + + public int getMaxBytesPerChar(Integer charsetIndex, String javaCharsetName) throws SQLException { + + return getActiveMySQLConnection().getMaxBytesPerChar(charsetIndex, javaCharsetName); + } + + public DatabaseMetaData getMetaData() throws SQLException { + + return getActiveMySQLConnection().getMetaData(); + } + + public Statement getMetadataSafeStatement() throws SQLException { + + return getActiveMySQLConnection().getMetadataSafeStatement(); + } + + public int getNetBufferLength() { + + return getActiveMySQLConnection().getNetBufferLength(); + } + + public Properties getProperties() { + + return getActiveMySQLConnection().getProperties(); + } + + public boolean getRequiresEscapingEncoder() { + + return getActiveMySQLConnection().getRequiresEscapingEncoder(); + } + + public String getServerCharacterEncoding() { + + return getActiveMySQLConnection().getServerCharacterEncoding(); + } + + public int getServerMajorVersion() { + + return getActiveMySQLConnection().getServerMajorVersion(); + } + + public int getServerMinorVersion() { + + return getActiveMySQLConnection().getServerMinorVersion(); + } + + public int getServerSubMinorVersion() { + + return getActiveMySQLConnection().getServerSubMinorVersion(); + } + + public TimeZone getServerTimezoneTZ() { + + return getActiveMySQLConnection().getServerTimezoneTZ(); + } + + public String getServerVariable(String variableName) { + + return getActiveMySQLConnection().getServerVariable(variableName); + } + + public String getServerVersion() { + + return getActiveMySQLConnection().getServerVersion(); + } + + public Calendar getSessionLockedCalendar() { + + return getActiveMySQLConnection().getSessionLockedCalendar(); + } + + public String getStatementComment() { + + return getActiveMySQLConnection().getStatementComment(); + } + + public List getStatementInterceptorsInstances() { + + return getActiveMySQLConnection().getStatementInterceptorsInstances(); + } + + public int getTransactionIsolation() throws SQLException { + + return getActiveMySQLConnection().getTransactionIsolation(); + } + + public Map> getTypeMap() throws SQLException { + + return getActiveMySQLConnection().getTypeMap(); + } + + public String getURL() { + + return getActiveMySQLConnection().getURL(); + } + + public String getUser() { + + return getActiveMySQLConnection().getUser(); + } + + public Calendar getUtcCalendar() { + + return getActiveMySQLConnection().getUtcCalendar(); + } + + public SQLWarning getWarnings() throws SQLException { + + return getActiveMySQLConnection().getWarnings(); + } + + public boolean hasSameProperties(Connection c) { + + return getActiveMySQLConnection().hasSameProperties(c); + } + + public boolean hasTriedMaster() { + + return getActiveMySQLConnection().hasTriedMaster(); + } + + public void incrementNumberOfPreparedExecutes() { + + getActiveMySQLConnection().incrementNumberOfPreparedExecutes(); + } + + public void incrementNumberOfPrepares() { + + getActiveMySQLConnection().incrementNumberOfPrepares(); + } + + public void incrementNumberOfResultSetsCreated() { + + getActiveMySQLConnection().incrementNumberOfResultSetsCreated(); + } + + public void initializeExtension(Extension ex) throws SQLException { + + getActiveMySQLConnection().initializeExtension(ex); + } + + public void initializeResultsMetadataFromCache(String sql, + CachedResultSetMetaData cachedMetaData, + ResultSetInternalMethods resultSet) throws SQLException { + + getActiveMySQLConnection().initializeResultsMetadataFromCache(sql, + cachedMetaData, resultSet); + } + + public void initializeSafeStatementInterceptors() throws SQLException { + + getActiveMySQLConnection().initializeSafeStatementInterceptors(); + } + + public boolean isAbonormallyLongQuery(long millisOrNanos) { + + return getActiveMySQLConnection().isAbonormallyLongQuery(millisOrNanos); + } + + public boolean isClientTzUTC() { + + return getActiveMySQLConnection().isClientTzUTC(); + } + + public boolean isCursorFetchEnabled() throws SQLException { + + return getActiveMySQLConnection().isCursorFetchEnabled(); + } + + public boolean isInGlobalTx() { + + return getActiveMySQLConnection().isInGlobalTx(); + } + + public boolean isMasterConnection() { + + return getActiveMySQLConnection().isMasterConnection(); + } + + public boolean isNoBackslashEscapesSet() { + + return getActiveMySQLConnection().isNoBackslashEscapesSet(); + } + + public boolean isReadInfoMsgEnabled() { + + return getActiveMySQLConnection().isReadInfoMsgEnabled(); + } + + public boolean isReadOnly() throws SQLException { + + return getActiveMySQLConnection().isReadOnly(); + } + + public boolean isReadOnly(boolean useSessionStatus) throws SQLException { + + return getActiveMySQLConnection().isReadOnly(useSessionStatus); + } + + public boolean isRunningOnJDK13() { + + return getActiveMySQLConnection().isRunningOnJDK13(); + } + + public boolean isSameResource(Connection otherConnection) { + + return getActiveMySQLConnection().isSameResource(otherConnection); + } + + public boolean isServerTzUTC() { + + return getActiveMySQLConnection().isServerTzUTC(); + } + + public boolean lowerCaseTableNames() { + + return getActiveMySQLConnection().lowerCaseTableNames(); + } + + public String nativeSQL(String sql) throws SQLException { + + return getActiveMySQLConnection().nativeSQL(sql); + } + + public boolean parserKnowsUnicode() { + + return getActiveMySQLConnection().parserKnowsUnicode(); + } + + public void ping() throws SQLException { + ping(true); + } + + public void ping(boolean allConnections) throws SQLException { + if(allConnections){ + this.proxy.doPing(); + } else { + getActiveMySQLConnection().ping(); + } + } + + public void pingInternal(boolean checkForClosedConnection, int timeoutMillis) + throws SQLException { + + getActiveMySQLConnection().pingInternal(checkForClosedConnection, + timeoutMillis); + } + + public CallableStatement prepareCall(String sql, int resultSetType, + int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + + return getActiveMySQLConnection().prepareCall(sql, resultSetType, + resultSetConcurrency, resultSetHoldability); + } + + public CallableStatement prepareCall(String sql, int resultSetType, + int resultSetConcurrency) throws SQLException { + + return getActiveMySQLConnection().prepareCall(sql, resultSetType, + resultSetConcurrency); + } + + public CallableStatement prepareCall(String sql) throws SQLException { + + return getActiveMySQLConnection().prepareCall(sql); + } + + public PreparedStatement prepareStatement(String sql, int resultSetType, + int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + + return getActiveMySQLConnection().prepareStatement(sql, resultSetType, + resultSetConcurrency, resultSetHoldability); + } + + public PreparedStatement prepareStatement(String sql, int resultSetType, + int resultSetConcurrency) throws SQLException { + + return getActiveMySQLConnection().prepareStatement(sql, resultSetType, + resultSetConcurrency); + } + + public PreparedStatement prepareStatement(String sql, int autoGenKeyIndex) + throws SQLException { + + return getActiveMySQLConnection() + .prepareStatement(sql, autoGenKeyIndex); + } + + public PreparedStatement prepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + + return getActiveMySQLConnection().prepareStatement(sql, + autoGenKeyIndexes); + } + + public PreparedStatement prepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + + return getActiveMySQLConnection().prepareStatement(sql, + autoGenKeyColNames); + } + + public PreparedStatement prepareStatement(String sql) throws SQLException { + + return getActiveMySQLConnection().prepareStatement(sql); + } + + public void realClose(boolean calledExplicitly, boolean issueRollback, + boolean skipLocalTeardown, Throwable reason) throws SQLException { + + getActiveMySQLConnection().realClose(calledExplicitly, issueRollback, + skipLocalTeardown, reason); + } + + public void recachePreparedStatement(ServerPreparedStatement pstmt) + throws SQLException { + + getActiveMySQLConnection().recachePreparedStatement(pstmt); + } + + public void decachePreparedStatement(ServerPreparedStatement pstmt) + throws SQLException { + + getActiveMySQLConnection().decachePreparedStatement(pstmt); + } + + public void registerQueryExecutionTime(long queryTimeMs) { + + getActiveMySQLConnection().registerQueryExecutionTime(queryTimeMs); + } + + public void registerStatement(com.mysql.jdbc.Statement stmt) { + + getActiveMySQLConnection().registerStatement(stmt); + } + + public void releaseSavepoint(Savepoint arg0) throws SQLException { + + getActiveMySQLConnection().releaseSavepoint(arg0); + } + + public void reportNumberOfTablesAccessed(int numTablesAccessed) { + + getActiveMySQLConnection().reportNumberOfTablesAccessed( + numTablesAccessed); + } + + public void reportQueryTime(long millisOrNanos) { + + getActiveMySQLConnection().reportQueryTime(millisOrNanos); + } + + public void resetServerState() throws SQLException { + + getActiveMySQLConnection().resetServerState(); + } + + public void rollback() throws SQLException { + + getActiveMySQLConnection().rollback(); + } + + public void rollback(Savepoint savepoint) throws SQLException { + + getActiveMySQLConnection().rollback(savepoint); + } + + public PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + + return getActiveMySQLConnection().serverPrepareStatement(sql, + resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + + return getActiveMySQLConnection().serverPrepareStatement(sql, + resultSetType, resultSetConcurrency); + } + + public PreparedStatement serverPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + + return getActiveMySQLConnection().serverPrepareStatement(sql, + autoGenKeyIndex); + } + + public PreparedStatement serverPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + + return getActiveMySQLConnection().serverPrepareStatement(sql, + autoGenKeyIndexes); + } + + public PreparedStatement serverPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + + return getActiveMySQLConnection().serverPrepareStatement(sql, + autoGenKeyColNames); + } + + public PreparedStatement serverPrepareStatement(String sql) + throws SQLException { + + return getActiveMySQLConnection().serverPrepareStatement(sql); + } + + public boolean serverSupportsConvertFn() throws SQLException { + + return getActiveMySQLConnection().serverSupportsConvertFn(); + } + + public void setAutoCommit(boolean autoCommitFlag) throws SQLException { + + getActiveMySQLConnection().setAutoCommit(autoCommitFlag); + } + + public void setCatalog(String catalog) throws SQLException { + + getActiveMySQLConnection().setCatalog(catalog); + } + + public void setFailedOver(boolean flag) { + + getActiveMySQLConnection().setFailedOver(flag); + } + + public void setHoldability(int arg0) throws SQLException { + + getActiveMySQLConnection().setHoldability(arg0); + } + + public void setInGlobalTx(boolean flag) { + + getActiveMySQLConnection().setInGlobalTx(flag); + } + + public void setPreferSlaveDuringFailover(boolean flag) { + + getActiveMySQLConnection().setPreferSlaveDuringFailover(flag); + } + + public void setProxy(MySQLConnection proxy) { + + getActiveMySQLConnection().setProxy(proxy); + } + + public void setReadInfoMsgEnabled(boolean flag) { + + getActiveMySQLConnection().setReadInfoMsgEnabled(flag); + } + + public void setReadOnly(boolean readOnlyFlag) throws SQLException { + + getActiveMySQLConnection().setReadOnly(readOnlyFlag); + } + + public void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException { + getActiveMySQLConnection().setReadOnlyInternal(readOnlyFlag); + } + + public Savepoint setSavepoint() throws SQLException { + return getActiveMySQLConnection().setSavepoint(); + } + + public Savepoint setSavepoint(String name) throws SQLException { + return getActiveMySQLConnection().setSavepoint(name); + } + + public void setStatementComment(String comment) { + getActiveMySQLConnection().setStatementComment(comment); + } + + public void setTransactionIsolation(int level) + throws SQLException { + getActiveMySQLConnection().setTransactionIsolation(level); + } + + + public void shutdownServer() throws SQLException { + getActiveMySQLConnection().shutdownServer(); + } + + public boolean storesLowerCaseTableName() { + return getActiveMySQLConnection().storesLowerCaseTableName(); + } + + public boolean supportsIsolationLevel() { + return getActiveMySQLConnection().supportsIsolationLevel(); + } + + public boolean supportsQuotedIdentifiers() { + return getActiveMySQLConnection().supportsQuotedIdentifiers(); + } + + public boolean supportsTransactions() { + return getActiveMySQLConnection().supportsTransactions(); + } + + public void throwConnectionClosedException() throws SQLException { + getActiveMySQLConnection().throwConnectionClosedException(); + } + + public void transactionBegun() throws SQLException { + getActiveMySQLConnection().transactionBegun(); + } + + public void transactionCompleted() throws SQLException { + getActiveMySQLConnection().transactionCompleted(); + } + + public void unregisterStatement(com.mysql.jdbc.Statement stmt) { + getActiveMySQLConnection().unregisterStatement(stmt); + } + + public void unSafeStatementInterceptors() throws SQLException { + getActiveMySQLConnection().unSafeStatementInterceptors(); + } + + public boolean useAnsiQuotedIdentifiers() { + return getActiveMySQLConnection().useAnsiQuotedIdentifiers(); + } + + public boolean versionMeetsMinimum(int major, int minor, int subminor) + throws SQLException { + return getActiveMySQLConnection().versionMeetsMinimum(major, minor, + subminor); + } + + public boolean isClosed() throws SQLException { + return getActiveMySQLConnection().isClosed(); + } + + public boolean getHoldResultsOpenOverStatementClose() { + return getActiveMySQLConnection() + .getHoldResultsOpenOverStatementClose(); + } + + public String getLoadBalanceConnectionGroup() { + return getActiveMySQLConnection().getLoadBalanceConnectionGroup(); + } + + public boolean getLoadBalanceEnableJMX() { + return getActiveMySQLConnection().getLoadBalanceEnableJMX(); + } + + public String getLoadBalanceExceptionChecker() { + return getActiveMySQLConnection() + .getLoadBalanceExceptionChecker(); + } + + public String getLoadBalanceSQLExceptionSubclassFailover() { + return getActiveMySQLConnection() + .getLoadBalanceSQLExceptionSubclassFailover(); + } + + public String getLoadBalanceSQLStateFailover() { + return getActiveMySQLConnection() + .getLoadBalanceSQLStateFailover(); + } + + public void setLoadBalanceConnectionGroup(String loadBalanceConnectionGroup) { + getActiveMySQLConnection() + .setLoadBalanceConnectionGroup(loadBalanceConnectionGroup); + + } + + public void setLoadBalanceEnableJMX(boolean loadBalanceEnableJMX) { + getActiveMySQLConnection() + .setLoadBalanceEnableJMX(loadBalanceEnableJMX); + + } + + public void setLoadBalanceExceptionChecker( + String loadBalanceExceptionChecker) { + getActiveMySQLConnection() + .setLoadBalanceExceptionChecker(loadBalanceExceptionChecker); + + } + + public void setLoadBalanceSQLExceptionSubclassFailover( + String loadBalanceSQLExceptionSubclassFailover) { + getActiveMySQLConnection() + .setLoadBalanceSQLExceptionSubclassFailover(loadBalanceSQLExceptionSubclassFailover); + + } + + public void setLoadBalanceSQLStateFailover( + String loadBalanceSQLStateFailover) { + getActiveMySQLConnection() + .setLoadBalanceSQLStateFailover(loadBalanceSQLStateFailover); + + } + + /** + * + * @param SQL + * @return + */ + public boolean shouldExecutionTriggerServerSwapAfter(String SQL){ + return false; + } + + public boolean isProxySet() { + return this.getActiveMySQLConnection().isProxySet(); + } + + + public String getLoadBalanceAutoCommitStatementRegex() { + return getActiveMySQLConnection() + .getLoadBalanceAutoCommitStatementRegex(); + } + + public int getLoadBalanceAutoCommitStatementThreshold() { + return getActiveMySQLConnection() + .getLoadBalanceAutoCommitStatementThreshold(); + } + + public void setLoadBalanceAutoCommitStatementRegex( + String loadBalanceAutoCommitStatementRegex) { + getActiveMySQLConnection() + .setLoadBalanceAutoCommitStatementRegex(loadBalanceAutoCommitStatementRegex); + + } + + public void setLoadBalanceAutoCommitStatementThreshold( + int loadBalanceAutoCommitStatementThreshold) throws SQLException { + getActiveMySQLConnection() + .setLoadBalanceAutoCommitStatementThreshold(loadBalanceAutoCommitStatementThreshold); + + } + + public boolean getIncludeThreadDumpInDeadlockExceptions() { + return getActiveMySQLConnection().getIncludeThreadDumpInDeadlockExceptions(); + } + + public void setIncludeThreadDumpInDeadlockExceptions(boolean flag) { + getActiveMySQLConnection().setIncludeThreadDumpInDeadlockExceptions(flag); + } + + public void setTypeMap(Map> map) throws SQLException { + getActiveMySQLConnection().setTypeMap(map); + } + + public boolean getIncludeThreadNamesAsStatementComment() { + return getActiveMySQLConnection().getIncludeThreadNamesAsStatementComment(); + } + + public void setIncludeThreadNamesAsStatementComment(boolean flag) { + getActiveMySQLConnection().setIncludeThreadNamesAsStatementComment(flag); + } + + public boolean isServerLocal() throws SQLException { + return getActiveMySQLConnection().isServerLocal(); + } + + public void setAuthenticationPlugins(String authenticationPlugins) { + getActiveMySQLConnection().setAuthenticationPlugins(authenticationPlugins); + } + + public String getAuthenticationPlugins() { + return getActiveMySQLConnection().getAuthenticationPlugins(); + } + + public void setDisabledAuthenticationPlugins( + String disabledAuthenticationPlugins) { + getActiveMySQLConnection().setDisabledAuthenticationPlugins(disabledAuthenticationPlugins); + } + + public String getDisabledAuthenticationPlugins() { + return getActiveMySQLConnection().getDisabledAuthenticationPlugins(); + } + + public void setDefaultAuthenticationPlugin( + String defaultAuthenticationPlugin) { + getActiveMySQLConnection().setDefaultAuthenticationPlugin(defaultAuthenticationPlugin); + } + + public String getDefaultAuthenticationPlugin() { + return getActiveMySQLConnection().getDefaultAuthenticationPlugin(); + } + + public void setParseInfoCacheFactory(String factoryClassname) { + getActiveMySQLConnection().setParseInfoCacheFactory(factoryClassname); + } + + public String getParseInfoCacheFactory() { + return getActiveMySQLConnection().getParseInfoCacheFactory(); + } + + public void setSchema(String schema) throws SQLException { + getActiveMySQLConnection().setSchema(schema); + } + + public String getSchema() throws SQLException { + return getActiveMySQLConnection().getSchema(); + } + + public void abort(Executor executor) throws SQLException { + getActiveMySQLConnection().abort(executor); + } + + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException { + getActiveMySQLConnection().setNetworkTimeout(executor, milliseconds); + } + + public int getNetworkTimeout() throws SQLException { + return getActiveMySQLConnection().getNetworkTimeout(); + } + + public void setServerConfigCacheFactory(String factoryClassname) { + getActiveMySQLConnection().setServerConfigCacheFactory(factoryClassname); + } + + public String getServerConfigCacheFactory() { + return getActiveMySQLConnection().getServerConfigCacheFactory(); + } + + public void setDisconnectOnExpiredPasswords(boolean disconnectOnExpiredPasswords) { + getActiveMySQLConnection().setDisconnectOnExpiredPasswords(disconnectOnExpiredPasswords); + } + + public boolean getDisconnectOnExpiredPasswords() { + return getActiveMySQLConnection().getDisconnectOnExpiredPasswords(); + } + + public void setGetProceduresReturnsFunctions(boolean getProcedureReturnsFunctions) { + getActiveMySQLConnection().setGetProceduresReturnsFunctions(getProcedureReturnsFunctions); + } + + public boolean getGetProceduresReturnsFunctions() { + return getActiveMySQLConnection().getGetProceduresReturnsFunctions(); + } + + public Object getConnectionMutex() { + return getActiveMySQLConnection().getConnectionMutex(); + } + + public String getConnectionAttributes() throws SQLException { + return getActiveMySQLConnection().getConnectionAttributes(); + } + + public boolean addHost(String host) throws SQLException { + return this.proxy.addHost(host); + } + + public void removeHost(String host) throws SQLException { + this.proxy.removeHost(host); + } + + public void removeHostWhenNotInUse(String host) throws SQLException { + this.proxy.removeHostWhenNotInUse(host); + + } + + public boolean getAllowMasterDownConnections() { + return false; + } + + public void setAllowMasterDownConnections(boolean connectIfMasterDown) { + // don't do anything here + } + + public boolean getReplicationEnableJMX() { + return false; + } + + public void setReplicationEnableJMX(boolean replicationEnableJMX) { + // nothing to do here. + + } + + public void setDetectCustomCollations(boolean detectCustomCollations) { + getActiveMySQLConnection().setDetectCustomCollations(detectCustomCollations); + } + + public boolean getDetectCustomCollations() { + return getActiveMySQLConnection().getDetectCustomCollations(); + } + + public int getSessionMaxRows() { + return getActiveMySQLConnection().getSessionMaxRows(); + } + + public void setSessionMaxRows(int max) throws SQLException { + getActiveMySQLConnection().setSessionMaxRows(max); + } + + public ProfilerEventHandler getProfilerEventHandlerInstance() { + return getActiveMySQLConnection().getProfilerEventHandlerInstance(); + } + + public void setProfilerEventHandlerInstance(ProfilerEventHandler h) { + getActiveMySQLConnection().setProfilerEventHandlerInstance(h); + } + + public String getServerRSAPublicKeyFile() { + return getActiveMySQLConnection().getServerRSAPublicKeyFile(); + } + + public void setServerRSAPublicKeyFile(String serverRSAPublicKeyFile) throws SQLException { + getActiveMySQLConnection().setServerRSAPublicKeyFile(serverRSAPublicKeyFile); + } + + public boolean getAllowPublicKeyRetrieval() { + return getActiveMySQLConnection().getAllowPublicKeyRetrieval(); + } + + public void setAllowPublicKeyRetrieval(boolean allowPublicKeyRetrieval) throws SQLException { + getActiveMySQLConnection().setAllowPublicKeyRetrieval(allowPublicKeyRetrieval); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancingConnectionProxy.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancingConnectionProxy.java (.../LoadBalancingConnectionProxy.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LoadBalancingConnectionProxy.java (.../LoadBalancingConnectionProxy.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,38 +1,44 @@ /* - Copyright (C) 2007 MySQL AB + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ package com.mysql.jdbc; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; +import java.util.concurrent.Executor; /** * An implementation of java.sql.Connection that load balances requests across a @@ -43,9 +49,10 @@ * reading data. * * This implementation will invalidate connections that it detects have had - * communication errors when processing a request. A new connection to the - * problematic host will be attempted the next time it is selected by the load - * balancing algorithm. + * communication errors when processing a request. Problematic hosts will be + * added to a global blacklist for loadBalanceBlacklistTimeout ms, after which + * they will be removed from the blacklist and made eligible once again to be + * selected for new connections. * * This implementation is thread-safe, but it's questionable whether sharing a * connection instance amongst threads is a good idea, given that transactions @@ -54,10 +61,23 @@ * @version $Id$ * */ -public class LoadBalancingConnectionProxy implements InvocationHandler, PingTarget { +public class LoadBalancingConnectionProxy implements InvocationHandler, + PingTarget { private static Method getLocalTimeMethod; + + private long totalPhysicalConnections = 0; + private long activePhysicalConnections = 0; + private String hostToRemove = null; + private long lastUsed = 0; + private long transactionCount = 0; + private ConnectionGroup connectionGroup = null; + protected String closedReason = null; + protected boolean closedExplicitly = false; + protected boolean autoReconnect = false; + public static final String BLACKLIST_TIMEOUT_PROPERTY_KEY = "loadBalanceBlacklistTimeout"; + static { try { getLocalTimeMethod = System.class.getMethod("nanoTime", @@ -69,87 +89,6 @@ } } - interface BalanceStrategy { - abstract Connection pickConnection() throws SQLException; - } - - class BestResponseTimeBalanceStrategy implements BalanceStrategy { - - public Connection pickConnection() throws SQLException { - long minResponseTime = Long.MAX_VALUE; - - int bestHostIndex = 0; - - long[] localResponseTimes = new long[responseTimes.length]; - - synchronized (responseTimes) { - System.arraycopy(responseTimes, 0, localResponseTimes, 0, responseTimes.length); - } - - SQLException ex = null; - - for (int attempts = 0; attempts < 1200 /* 5 minutes */; attempts++) { - for (int i = 0; i < localResponseTimes.length; i++) { - long candidateResponseTime = localResponseTimes[i]; - - if (candidateResponseTime < minResponseTime) { - if (candidateResponseTime == 0) { - bestHostIndex = i; - - break; - } - - bestHostIndex = i; - minResponseTime = candidateResponseTime; - } - } - - if (bestHostIndex == localResponseTimes.length - 1) { - // try again, assuming that the previous list was mostly - // correct as far as distribution of response times went - - synchronized (responseTimes) { - System.arraycopy(responseTimes, 0, localResponseTimes, 0, responseTimes.length); - } - - continue; - } - String bestHost = (String) hostList.get(bestHostIndex); - - Connection conn = (Connection) liveConnections.get(bestHost); - - if (conn == null) { - try { - conn = createConnectionForHost(bestHost); - } catch (SQLException sqlEx) { - ex = sqlEx; - - if (sqlEx instanceof CommunicationsException || "08S01".equals(sqlEx.getSQLState())) { - localResponseTimes[bestHostIndex] = Long.MAX_VALUE; - - try { - Thread.sleep(250); - } catch (InterruptedException e) { - } - - continue; - } else { - throw sqlEx; - } - } - } - - return conn; - } - - if (ex != null) { - throw ex; - } - - return null; // we won't get here, compiler can't tell - } - } - // Lifted from C/J 5.1's JDBC-2.0 connection pool classes, let's merge this // if/when this gets into 5.1 protected class ConnectionErrorFiringInvocationHandler implements @@ -178,76 +117,68 @@ } } - class RandomBalanceStrategy implements BalanceStrategy { + protected MySQLConnection currentConn; - public Connection pickConnection() throws SQLException { - int random = (int) (Math.random() * hostList.size()); + protected List hostList; - if (random == hostList.size()) { - random--; - } + protected Map liveConnections; - String hostPortSpec = (String) hostList.get(random); + private Map connectionsToHostsMap; - SQLException ex = null; - - for (int attempts = 0; attempts < 1200 /* 5 minutes */; attempts++) { - Connection conn = (Connection) liveConnections.get(hostPortSpec); - - if (conn == null) { - try { - conn = createConnectionForHost(hostPortSpec); - } catch (SQLException sqlEx) { - ex = sqlEx; - - if (sqlEx instanceof CommunicationsException || "08S01".equals(sqlEx.getSQLState())) { - - try { - Thread.sleep(250); - } catch (InterruptedException e) { - } - - continue; - } else { - throw sqlEx; - } - } - } - - return conn; - } - - if (ex != null) { - throw ex; - } - - return null; // we won't get here, compiler can't tell - } + private long[] responseTimes; - } + private Map hostsToListIndexMap; - private Connection currentConn; + private boolean inTransaction = false; - private List hostList; + private long transactionStartTime = 0; - private Map liveConnections; + private Properties localProps; - private Map connectionsToHostsMap; + protected boolean isClosed = false; - private long[] responseTimes; + private BalanceStrategy balancer; - private Map hostsToListIndexMap; + private int retriesAllDown; - boolean inTransaction = false; + private static Map globalBlacklist = new HashMap(); - long transactionStartTime = 0; + private int globalBlacklistTimeout = 0; + + private long connectionGroupProxyID = 0; - Properties localProps; + private LoadBalanceExceptionChecker exceptionChecker; - boolean isClosed = false; + private Map, Boolean> jdbcInterfacesForProxyCache = new HashMap, Boolean>(); + + private MySQLConnection thisAsConnection = null; - BalanceStrategy balancer; + private int autoCommitSwapThreshold = 0; + + private static Constructor JDBC_4_LB_CONNECTION_CTOR; + + static { + if(Util.isJdbc4()){ + try { + JDBC_4_LB_CONNECTION_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4LoadBalancedMySQLConnection").getConstructor( + new Class[] { LoadBalancingConnectionProxy.class}); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + } + + + + + + /** * Creates a proxy for java.sql.Connection that routes requests between the * given list of host:port and uses the given properties when creating @@ -257,40 +188,153 @@ * @param props * @throws SQLException */ - LoadBalancingConnectionProxy(List hosts, Properties props) + LoadBalancingConnectionProxy(List hosts, Properties props) throws SQLException { + String group = props.getProperty("loadBalanceConnectionGroup", + null); + boolean enableJMX = false; + String enableJMXAsString = props.getProperty("loadBalanceEnableJMX", + "false"); + try{ + enableJMX = Boolean.parseBoolean(enableJMXAsString); + } catch (Exception e){ + throw SQLError.createSQLException(Messages.getString( + "LoadBalancingConnectionProxy.badValueForLoadBalanceEnableJMX", + new Object[] { enableJMXAsString }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + + if(group != null){ + this.connectionGroup = ConnectionGroupManager.getConnectionGroupInstance(group); + if(enableJMX){ + ConnectionGroupManager.registerJmx(); + } + this.connectionGroupProxyID = this.connectionGroup.registerConnectionProxy(this, hosts); + hosts = new ArrayList(this.connectionGroup.getInitialHosts()); + } + + this.autoReconnect = "true".equalsIgnoreCase(props.getProperty("autoReconnect")) || + "true".equalsIgnoreCase(props.getProperty("autoReconnectForPools")); + this.hostList = hosts; int numHosts = this.hostList.size(); - this.liveConnections = new HashMap(numHosts); - this.connectionsToHostsMap = new HashMap(numHosts); + this.liveConnections = new HashMap(numHosts); + this.connectionsToHostsMap = new HashMap(numHosts); this.responseTimes = new long[numHosts]; - this.hostsToListIndexMap = new HashMap(numHosts); + this.hostsToListIndexMap = new HashMap(numHosts); - for (int i = 0; i < numHosts; i++) { - this.hostsToListIndexMap.put(this.hostList.get(i), new Integer(i)); - } - this.localProps = (Properties) props.clone(); this.localProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY); this.localProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY); + + for (int i = 0; i < numHosts; i++) { + this.hostsToListIndexMap.put(this.hostList.get(i), Integer.valueOf(i)); + this.localProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY + "." + + (i + 1)); + this.localProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY + "." + + (i + 1)); + } + + this.localProps.remove(NonRegisteringDriver.NUM_HOSTS_PROPERTY_KEY); this.localProps.setProperty("useLocalSessionState", "true"); String strategy = this.localProps.getProperty("loadBalanceStrategy", "random"); + + String lbExceptionChecker = this.localProps.getProperty("loadBalanceExceptionChecker", + "com.mysql.jdbc.StandardLoadBalanceExceptionChecker"); + + String retriesAllDownAsString = this.localProps.getProperty( + "retriesAllDown", "120"); + + try { + this.retriesAllDown = Integer.parseInt(retriesAllDownAsString); + } catch (NumberFormatException nfe) { + throw SQLError.createSQLException(Messages.getString( + "LoadBalancingConnectionProxy.badValueForRetriesAllDown", + new Object[] { retriesAllDownAsString }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + String blacklistTimeoutAsString = this.localProps.getProperty( + BLACKLIST_TIMEOUT_PROPERTY_KEY, "0"); + + try { + this.globalBlacklistTimeout = Integer + .parseInt(blacklistTimeoutAsString); + } catch (NumberFormatException nfe) { + throw SQLError + .createSQLException( + Messages + .getString( + "LoadBalancingConnectionProxy.badValueForLoadBalanceBlacklistTimeout", + new Object[] { retriesAllDownAsString }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + if ("random".equals(strategy)) { - this.balancer = new RandomBalanceStrategy(); + this.balancer = (BalanceStrategy) Util.loadExtensions(null, props, + "com.mysql.jdbc.RandomBalanceStrategy", + "InvalidLoadBalanceStrategy", null).get(0); } else if ("bestResponseTime".equals(strategy)) { - this.balancer = new BestResponseTimeBalanceStrategy(); + this.balancer = (BalanceStrategy) Util.loadExtensions(null, props, + "com.mysql.jdbc.BestResponseTimeBalanceStrategy", + "InvalidLoadBalanceStrategy", null).get(0); } else { + this.balancer = (BalanceStrategy) Util.loadExtensions(null, props, + strategy, "InvalidLoadBalanceStrategy", null).get(0); + } + + String autoCommitSwapThresholdAsString = props.getProperty("loadBalanceAutoCommitStatementThreshold", + "0"); + try { + this.autoCommitSwapThreshold = Integer.parseInt(autoCommitSwapThresholdAsString); + } catch (NumberFormatException nfe) { throw SQLError.createSQLException(Messages.getString( - "InvalidLoadBalanceStrategy", new Object[] { strategy }), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + "LoadBalancingConnectionProxy.badValueForLoadBalanceAutoCommitStatementThreshold", + new Object[] { autoCommitSwapThresholdAsString }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); } + + String autoCommitSwapRegex = props.getProperty("loadBalanceAutoCommitStatementRegex",""); + if(!("".equals(autoCommitSwapRegex))){ + try{ + "".matches(autoCommitSwapRegex); + } catch (Exception e){ + throw SQLError.createSQLException(Messages.getString( + "LoadBalancingConnectionProxy.badValueForLoadBalanceAutoCommitStatementRegex", + new Object[] { autoCommitSwapRegex }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + } + + if(this.autoCommitSwapThreshold > 0){ + String statementInterceptors = this.localProps.getProperty("statementInterceptors"); + if(statementInterceptors == null){ + this.localProps.setProperty("statementInterceptors", "com.mysql.jdbc.LoadBalancedAutoCommitInterceptor"); + } else if(statementInterceptors.length() > 0){ + this.localProps.setProperty("statementInterceptors", statementInterceptors + ",com.mysql.jdbc.LoadBalancedAutoCommitInterceptor"); + } + props.setProperty("statementInterceptors", this.localProps.getProperty("statementInterceptors")); + + } + this.balancer.init(null, props); + + this.exceptionChecker = (LoadBalanceExceptionChecker) Util.loadExtensions(null, props, + lbExceptionChecker, "InvalidLoadBalanceExceptionChecker", null).get(0); + + if(Util.isJdbc4() || JDBC_4_LB_CONNECTION_CTOR != null){ + thisAsConnection = (MySQLConnection) Util.handleNewInstance(JDBC_4_LB_CONNECTION_CTOR, + new Object[] {this}, null); + }else{ + thisAsConnection = new LoadBalancedMySQLConnection(this); + } pickNewConnection(); + + } /** @@ -301,30 +345,56 @@ * @return * @throws SQLException */ - private synchronized Connection createConnectionForHost(String hostPortSpec) - throws SQLException { + public synchronized ConnectionImpl createConnectionForHost( + String hostPortSpec) throws SQLException { Properties connProps = (Properties) this.localProps.clone(); String[] hostPortPair = NonRegisteringDriver .parseHostPortPair(hostPortSpec); + String hostName = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX]; + String portNumber = hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]; + String dbName = connProps + .getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY); - if (hostPortPair[1] == null) { - hostPortPair[1] = "3306"; + if (hostName == null) { + throw new SQLException( + "Could not find a hostname to start a connection to"); } + if (portNumber == null) { + portNumber = "3306";// use default + } - connProps.setProperty(NonRegisteringDriver.HOST_PROPERTY_KEY, - hostPortSpec); + connProps.setProperty(NonRegisteringDriver.HOST_PROPERTY_KEY, hostName); connProps.setProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, - hostPortPair[1]); + portNumber); + connProps.setProperty(NonRegisteringDriver.HOST_PROPERTY_KEY + ".1", + hostName); + connProps.setProperty(NonRegisteringDriver.PORT_PROPERTY_KEY + ".1", + portNumber); + connProps.setProperty(NonRegisteringDriver.NUM_HOSTS_PROPERTY_KEY, "1"); + connProps.setProperty("roundRobinLoadBalance", "false"); // make sure we + // don't + // pickup + // the + // default + // value - Connection conn = new Connection(hostPortSpec, Integer - .parseInt(hostPortPair[1]), connProps, connProps - .getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY), - "jdbc:mysql://" + hostPortPair[0] + ":" + hostPortPair[1] + "/"); + ConnectionImpl conn = (ConnectionImpl) ConnectionImpl.getInstance( + hostName, Integer.parseInt(portNumber), connProps, dbName, + "jdbc:mysql://" + hostName + ":" + portNumber + "/"); + + this.liveConnections.put(hostPortSpec, conn); this.connectionsToHostsMap.put(conn, hostPortSpec); + + this.activePhysicalConnections++; + this.totalPhysicalConnections++; + + conn.setProxy(this.thisAsConnection); + conn.setRealProxy(this); + return conn; } @@ -339,16 +409,9 @@ Throwable t = e.getTargetException(); if (t != null) { - if (t instanceof SQLException) { - String sqlState = ((SQLException) t).getSQLState(); - - if (sqlState != null) { - if (sqlState.startsWith("08")) { - // connection error, close up shop on current - // connection - invalidateCurrentConnection(); - } - } + if (t instanceof SQLException && shouldExceptionTriggerFailover((SQLException) t )) { + invalidateCurrentConnection(); + pickNewConnection(); } throw t; @@ -363,88 +426,251 @@ * @throws SQLException */ synchronized void invalidateCurrentConnection() throws SQLException { + invalidateConnection(this.currentConn); + } + + + /** + * Closes specified connection and removes it from required mappings. + * @param conn + * @throws SQLException + */ + synchronized void invalidateConnection(MySQLConnection conn) throws SQLException { try { - if (!this.currentConn.isClosed()) { - this.currentConn.close(); + if (!conn.isClosed()) { + conn.close(); } - + } catch (SQLException e) { + // we don't really want to throw this Exception } finally { + // add host to the global blacklist, if enabled + if (this.isGlobalBlacklistEnabled()) { + this.addToGlobalBlacklist(this.connectionsToHostsMap + .get(conn)); + + } + // remove from liveConnections this.liveConnections.remove(this.connectionsToHostsMap - .get(this.currentConn)); - this.connectionsToHostsMap.remove(this.currentConn); + .get(conn)); + Object mappedHost = this.connectionsToHostsMap + .remove(conn); + if (mappedHost != null + && this.hostsToListIndexMap.containsKey(mappedHost)) { + int hostIndex = (this.hostsToListIndexMap + .get(mappedHost)).intValue(); + // reset the statistics for the host + synchronized (this.responseTimes) { + this.responseTimes[hostIndex] = 0; + } + } + } + } + + + private void closeAllConnections() { + synchronized (this) { + // close all underlying connections + Iterator allConnections = this.liveConnections.values().iterator(); + + while (allConnections.hasNext()) { + try { + this.activePhysicalConnections--; + allConnections.next().close(); + } catch (SQLException e) { + } + } + + if (!this.isClosed) { + this.balancer.destroy(); + if(this.connectionGroup != null){ + this.connectionGroup.closeConnectionProxy(this); + } + } + + this.liveConnections.clear(); + this.connectionsToHostsMap.clear(); } + } + + private void abortAllConnectionsInternal() { + synchronized (this) { + // abort all underlying connections + Iterator allConnections = this.liveConnections.values().iterator(); + while (allConnections.hasNext()) { + try { + this.activePhysicalConnections--; + allConnections.next().abortInternal(); + } catch (SQLException e) { + } + } + + if (!this.isClosed) { + this.balancer.destroy(); + if(this.connectionGroup != null){ + this.connectionGroup.closeConnectionProxy(this); + } + } + + this.liveConnections.clear(); + this.connectionsToHostsMap.clear(); + } + } + + private void abortAllConnections(Executor executor) { + synchronized (this) { + // close all underlying connections + Iterator allConnections = this.liveConnections.values().iterator(); + + while (allConnections.hasNext()) { + try { + this.activePhysicalConnections--; + allConnections.next().abort(executor); + } catch (SQLException e) { + } + } + + if (!this.isClosed) { + this.balancer.destroy(); + if(this.connectionGroup != null){ + this.connectionGroup.closeConnectionProxy(this); + } + } + + this.liveConnections.clear(); + this.connectionsToHostsMap.clear(); + } + + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return this.invoke(proxy, method, args, true); + } + /** * Proxies method invocation on the java.sql.Connection interface, trapping * "close", "isClosed" and "commit/rollback" (to switch connections for load * balancing). + * + * @param proxy + * @param method + * @param args + * @param swapAtTransactionBoundary + * @return + * @throws Throwable */ - public Object invoke(Object proxy, Method method, Object[] args) + public synchronized Object invoke(Object proxy, Method method, Object[] args, boolean swapAtTransactionBoundary) throws Throwable { String methodName = method.getName(); + + if("getLoadBalanceSafeProxy".equals(methodName)){ + return this.currentConn; + } + if ("equals".equals(methodName) && args.length == 1) { + if (args[0] instanceof Proxy) { + return Boolean.valueOf((((Proxy) args[0]).equals(this))); + } + return Boolean.valueOf(this.equals(args[0])); + } + + if ("hashCode".equals(methodName)) { + return Integer.valueOf(this.hashCode()); + } + if ("close".equals(methodName)) { - synchronized (this.liveConnections) { - // close all underlying connections - Iterator allConnections = this.liveConnections.values() - .iterator(); + closeAllConnections(); - while (allConnections.hasNext()) { - ((Connection) allConnections.next()).close(); - } + this.isClosed = true; + this.closedReason = "Connection explicitly closed."; + this.closedExplicitly = true; - this.liveConnections.clear(); - this.connectionsToHostsMap.clear(); - } + return null; + } + if ("abortInternal".equals(methodName)) { + abortAllConnectionsInternal(); + this.isClosed = true; + this.closedReason = "Connection explicitly closed."; return null; } + if ("abort".equals(methodName) && args.length == 1) { + abortAllConnections((Executor)args[0]); + this.isClosed = true; + this.closedReason = "Connection explicitly closed."; + return null; + } + if ("isClosed".equals(methodName)) { return Boolean.valueOf(this.isClosed); } if (this.isClosed) { - throw SQLError.createSQLException( - "No operations allowed after connection closed.", - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); + if(this.autoReconnect && !this.closedExplicitly){ + // try to reconnect first! + this.currentConn = null; + this.pickNewConnection(); + this.isClosed = false; + this.closedReason = null; + } else { + String reason = "No operations allowed after connection closed."; + if(this.closedReason != null){ + reason += (" " + this.closedReason); + } + throw SQLError.createSQLException( + reason, + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, null /* + * no access to + * a interceptor + * here... + */); + } } if (!inTransaction) { this.inTransaction = true; this.transactionStartTime = getLocalTimeBestResolution(); + this.transactionCount++; } Object result = null; try { - result = method.invoke(this.currentConn, args); + this.lastUsed = System.currentTimeMillis(); + result = method.invoke(thisAsConnection, args); if (result != null) { if (result instanceof com.mysql.jdbc.Statement) { - ((com.mysql.jdbc.Statement)result).setPingTarget(this); + ((com.mysql.jdbc.Statement) result).setPingTarget(this); } - + result = proxyIfInterfaceIsJdbc(result, result.getClass()); } } catch (InvocationTargetException e) { dealWithInvocationException(e); } finally { - if ("commit".equals(methodName) || "rollback".equals(methodName)) { + if (swapAtTransactionBoundary && ("commit".equals(methodName) || "rollback".equals(methodName))) { this.inTransaction = false; // Update stats - int hostIndex = ((Integer) this.hostsToListIndexMap - .get(this.connectionsToHostsMap.get(this.currentConn))) - .intValue(); + String host = this.connectionsToHostsMap.get(this.currentConn); + // avoid NPE if the connection has already been removed from + // connectionsToHostsMap + // in invalidateCurrenctConnection() + if (host != null) { + synchronized (this.responseTimes) { + Integer hostIndex = (this.hostsToListIndexMap + .get(host)); - synchronized (this.responseTimes) { - this.responseTimes[hostIndex] = getLocalTimeBestResolution() - - this.transactionStartTime; + if(hostIndex != null && hostIndex.intValue() < this.responseTimes.length){ + this.responseTimes[hostIndex] = getLocalTimeBestResolution() + - this.transactionStartTime; + } + } } - pickNewConnection(); } } @@ -458,19 +684,63 @@ * * @throws SQLException */ - private synchronized void pickNewConnection() throws SQLException { - if (this.currentConn == null) { - this.currentConn = this.balancer.pickConnection(); + protected synchronized void pickNewConnection() throws SQLException { + if (this.isClosed && this.closedExplicitly) { + return; + } + if (this.currentConn == null) { // startup + this.currentConn = this.balancer.pickConnection(this, Collections + .unmodifiableList(this.hostList), Collections + .unmodifiableMap(this.liveConnections), + this.responseTimes.clone(), this.retriesAllDown); return; } + + if(this.currentConn.isClosed()){ + invalidateCurrentConnection(); + } - Connection newConn = this.balancer.pickConnection(); + int pingTimeout = this.currentConn.getLoadBalancePingTimeout(); + boolean pingBeforeReturn = this.currentConn.getLoadBalanceValidateConnectionOnSwapServer(); + + for(int hostsTried = 0, hostsToTry = this.hostList.size(); hostsTried <= hostsToTry; hostsTried++){ + ConnectionImpl newConn = null; + try{ + newConn = this.balancer.pickConnection( - newConn.setTransactionIsolation(this.currentConn - .getTransactionIsolation()); - newConn.setAutoCommit(this.currentConn.getAutoCommit()); - this.currentConn = newConn; + this, Collections.unmodifiableList(this.hostList), Collections + .unmodifiableMap(this.liveConnections), + this.responseTimes.clone(), this.retriesAllDown); + + if (this.currentConn != null) { + if(pingBeforeReturn){ + if(pingTimeout == 0){ + newConn.ping(); + } else { + newConn.pingInternal(true, pingTimeout); + } + } + + syncSessionState(this.currentConn, newConn); + } + + this.currentConn = newConn; + return; + } catch (SQLException e){ + + if (shouldExceptionTriggerFailover(e) && newConn != null) { + // connection error, close up shop on current + // connection + invalidateConnection(newConn); + } + } + + } + // no hosts available to swap connection to, close up. + this.isClosed = true; + this.closedReason = "Connection closed after inability to pick valid new connection during fail-over."; + } /** @@ -482,33 +752,95 @@ * @param clazz * @return */ - Object proxyIfInterfaceIsJdbc(Object toProxy, Class clazz) { - Class[] interfaces = clazz.getInterfaces(); + Object proxyIfInterfaceIsJdbc(Object toProxy, Class clazz) { + + if(isInterfaceJdbc(clazz)){ + + Class[] interfacesToProxy = getAllInterfacesToProxy(clazz); + + return Proxy.newProxyInstance(toProxy.getClass() + .getClassLoader(), interfacesToProxy, + createConnectionProxy(toProxy)); + } + return toProxy; + } + + private Map, Class[]> allInterfacesToProxy = new HashMap, Class[]>(); + + private Class[] getAllInterfacesToProxy(Class clazz) { + Class[] interfacesToProxy = this.allInterfacesToProxy.get(clazz); + + if (interfacesToProxy != null) { + return interfacesToProxy; + } + + List> interfaces = new LinkedList>(); + + Class superClass = clazz; + + while (!(superClass.equals(Object.class))) { + Class[] declared = superClass.getInterfaces(); + + for (int i = 0; i < declared.length; i++) { + interfaces.add(declared[i]); + } + + superClass = superClass.getSuperclass(); + } + + interfacesToProxy = new Class[interfaces.size()]; + interfaces.toArray(interfacesToProxy); + + this.allInterfacesToProxy.put(clazz, interfacesToProxy); + + return interfacesToProxy; + } + + + private boolean isInterfaceJdbc(Class clazz){ + if(this.jdbcInterfacesForProxyCache.containsKey(clazz)){ + return (this.jdbcInterfacesForProxyCache.get(clazz)).booleanValue(); + } + + Class[] interfaces = clazz.getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { String packageName = interfaces[i].getPackage().getName(); if ("java.sql".equals(packageName) - || "javax.sql".equals(packageName)) { - return Proxy.newProxyInstance(toProxy.getClass() - .getClassLoader(), interfaces, - new ConnectionErrorFiringInvocationHandler(toProxy)); + || "javax.sql".equals(packageName) + || "com.mysql.jdbc".equals(packageName)) { + this.jdbcInterfacesForProxyCache.put(clazz, Boolean.valueOf(true)); + + return true; } - return proxyIfInterfaceIsJdbc(toProxy, interfaces[i]); + if(isInterfaceJdbc(interfaces[i])){ + this.jdbcInterfacesForProxyCache.put(clazz, Boolean.valueOf(true)); + + return true; + } } - return toProxy; + this.jdbcInterfacesForProxyCache.put(clazz, Boolean.valueOf(false)); + return false; + } + protected ConnectionErrorFiringInvocationHandler createConnectionProxy( + Object toProxy) { + return new ConnectionErrorFiringInvocationHandler(toProxy); + } + /** * Returns best-resolution representation of local time, using nanoTime() if - * availble, otherwise defaulting to currentTimeMillis(). + * available, otherwise defaulting to currentTimeMillis(). */ private static long getLocalTimeBestResolution() { if (getLocalTimeMethod != null) { try { - return ((Long) getLocalTimeMethod.invoke(null, null)) + return ((Long) getLocalTimeMethod.invoke(null, (Object[])null)) .longValue(); } catch (IllegalArgumentException e) { // ignore - we fall through to currentTimeMillis() @@ -523,10 +855,289 @@ } public synchronized void doPing() throws SQLException { - Iterator allConns = this.liveConnections.values().iterator(); + SQLException se = null; + boolean foundHost = false; + int pingTimeout = this.currentConn.getLoadBalancePingTimeout(); + synchronized (this) { + for (Iterator i = this.hostList.iterator(); i.hasNext();) { + String host = i.next(); + ConnectionImpl conn = this.liveConnections.get(host); + if (conn == null) { + continue; + } + try { + if(pingTimeout == 0){ + conn.ping(); + } else { + conn.pingInternal(true, pingTimeout); + } + foundHost = true; + } catch (SQLException e) { + this.activePhysicalConnections--; + // give up if it is the current connection, otherwise NPE + // faking resultset later. + if (host.equals(this.connectionsToHostsMap + .get(this.currentConn))) { + // clean up underlying connections, since connection + // pool won't do it + closeAllConnections(); + this.isClosed = true; + this.closedReason = "Connection closed because ping of current connection failed."; + throw e; + } + + // if the Exception is caused by ping connection lifetime + // checks, don't add to blacklist + if (e + .getMessage() + .equals( + Messages + .getString("Connection.exceededConnectionLifetime"))) { + // only set the return Exception if it's null + if (se == null) { + se = e; + } + } else { + // overwrite the return Exception no matter what + se = e; + if (this.isGlobalBlacklistEnabled()) { + this.addToGlobalBlacklist(host); + } + } + // take the connection out of the liveConnections Map + this.liveConnections.remove(this.connectionsToHostsMap + .get(conn)); + } + } + } + // if there were no successful pings + if (!foundHost) { + closeAllConnections(); + this.isClosed = true; + this.closedReason = "Connection closed due to inability to ping any active connections."; + // throw the stored Exception, if exists + if (se != null) { + throw se; + } + // or create a new SQLException and throw it, must be no + // liveConnections + ((ConnectionImpl) this.currentConn) + .throwConnectionClosedException(); + } + } + + public void addToGlobalBlacklist(String host, long timeout) { + if (this.isGlobalBlacklistEnabled()) { + synchronized (globalBlacklist) { + globalBlacklist.put(host, Long.valueOf(timeout)); + } + } + } + + public void addToGlobalBlacklist(String host){ + addToGlobalBlacklist(host, System.currentTimeMillis() + + this.globalBlacklistTimeout); - while (allConns.hasNext()) { - ((Connection)allConns.next()).ping(); + } + + public boolean isGlobalBlacklistEnabled() { + return (this.globalBlacklistTimeout > 0); + } + + public synchronized Map getGlobalBlacklist() { + if (!this.isGlobalBlacklistEnabled()) { + String localHostToRemove = this.hostToRemove; + + if(hostToRemove != null){ + HashMap fakedBlacklist = new HashMap(); + fakedBlacklist.put(localHostToRemove, Long.valueOf(System.currentTimeMillis() + 5000)); + return fakedBlacklist; + } + + return new HashMap(1); } + + // Make a local copy of the blacklist + Map blacklistClone = new HashMap(globalBlacklist.size()); + // Copy everything from synchronized global blacklist to local copy for + // manipulation + synchronized (globalBlacklist) { + blacklistClone.putAll(globalBlacklist); + } + Set keys = blacklistClone.keySet(); + + // we're only interested in blacklisted hosts that are in the hostList + keys.retainAll(this.hostList); + + // Don't need to synchronize here as we using a local copy + for (Iterator i = keys.iterator(); i.hasNext();) { + String host = i.next(); + // OK if null is returned because another thread already purged Map + // entry. + Long timeout = globalBlacklist.get(host); + if (timeout != null + && timeout.longValue() < System.currentTimeMillis()) { + // Timeout has expired, remove from blacklist + synchronized (globalBlacklist) { + globalBlacklist.remove(host); + } + i.remove(); + } + + } + if (keys.size() == this.hostList.size()) { + // return an empty blacklist, let the BalanceStrategy + // implementations try to connect to everything + // since it appears that all hosts are unavailable - we don't want + // to wait for + // loadBalanceBlacklistTimeout to expire. + return new HashMap(1); + } + + return blacklistClone; } + + public boolean shouldExceptionTriggerFailover(SQLException ex){ + return this.exceptionChecker.shouldExceptionTriggerFailover(ex); + + } + + public void removeHostWhenNotInUse(String host) + throws SQLException { + int timeBetweenChecks = 1000; + long timeBeforeHardFail = 15000; + + synchronized (this) { + addToGlobalBlacklist(host, timeBeforeHardFail + 1000); + + long cur = System.currentTimeMillis(); + + while (System.currentTimeMillis() - timeBeforeHardFail < cur) { + + this.hostToRemove = host; + + if (!host.equals(this.currentConn.getHost())) { + removeHost(host); + return; + } + } + } + + try { + Thread.sleep(timeBetweenChecks); + } catch (InterruptedException e) { + // better to swallow this and retry. + } + + removeHost(host); + } + + public synchronized void removeHost(String host) throws SQLException { + + if (this.connectionGroup != null) { + if (this.connectionGroup.getInitialHosts().size() == 1 + && this.connectionGroup.getInitialHosts().contains(host)) { + throw SQLError.createSQLException( + "Cannot remove only configured host.", null); + } + + this.hostToRemove = host; + + if (host.equals(this.currentConn.getHost())) { + closeAllConnections(); + } else { + this.connectionsToHostsMap.remove(this.liveConnections + .remove(host)); + Integer idx = this.hostsToListIndexMap.remove(host); + long[] newResponseTimes = new long[this.responseTimes.length - 1]; + int newIdx = 0; + for (Iterator i = this.hostList.iterator(); i.hasNext(); newIdx++) { + String copyHost = i.next(); + if (idx != null + && idx.intValue() < this.responseTimes.length) { + newResponseTimes[newIdx] = this.responseTimes[idx + .intValue()]; + this.hostsToListIndexMap.put(copyHost, + Integer.valueOf(newIdx)); + } + } + this.responseTimes = newResponseTimes; + } + } + + } + + public synchronized boolean addHost(String host) { + + if (this.hostsToListIndexMap.containsKey(host)) { + return false; + } + + long[] newResponseTimes = new long[this.responseTimes.length + 1]; + + System.arraycopy(this.responseTimes, 0, newResponseTimes, 0, this.responseTimes.length); + + this.responseTimes = newResponseTimes; + this.hostList.add(host); + this.hostsToListIndexMap.put(host, + Integer.valueOf(this.responseTimes.length - 1)); + + return true; + } + + public synchronized long getLastUsed(){ + return this.lastUsed; + } + + public synchronized boolean inTransaction(){ + return this.inTransaction; + } + + public synchronized long getTransactionCount(){ + return this.transactionCount; + } + + public synchronized long getActivePhysicalConnectionCount(){ + return this.activePhysicalConnections; + } + + public synchronized long getTotalPhysicalConnectionCount(){ + return this.totalPhysicalConnections; + } + + public synchronized long getConnectionGroupProxyID(){ + return this.connectionGroupProxyID; + } + + public synchronized String getCurrentActiveHost() { + MySQLConnection c = this.currentConn; + if(c != null){ + Object o = this.connectionsToHostsMap.get(c); + if(o != null){ + return o.toString(); + } + } + return null; + } + + public synchronized long getCurrentTransactionDuration(){ + + if (this.inTransaction && this.transactionStartTime > 0) { + return getLocalTimeBestResolution() - this.transactionStartTime; + } + + return 0; + } + + protected void syncSessionState(Connection initial, Connection target) + throws SQLException { + if (initial == null || target == null) { + return; + } + target.setAutoCommit(initial.getAutoCommit()); + target.setCatalog(initial.getCatalog()); + target.setTransactionIsolation(initial.getTransactionIsolation()); + target.setReadOnly(initial.isReadOnly()); + target.setSessionMaxRows(initial.getSessionMaxRows()); + } } \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/LocalizedErrorMessages.properties =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/LocalizedErrorMessages.properties (.../LocalizedErrorMessages.properties) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/LocalizedErrorMessages.properties (.../LocalizedErrorMessages.properties) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -37,7 +37,8 @@ Statement.61=Can not issue empty query. Statement.63=Statement not closed explicitly. You should call close() on created Statement.64=Statement instances from your code to be more efficient. - +Statement.GeneratedKeysNotRequested=Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate() or Connection.prepareStatement(). +Statement.ConnectionKilledDueToTimeout=Connection closed to due to statement timeout being reached and "queryTimeoutKillsConnection" being set to "true". UpdatableResultSet.1=Can not call deleteRow() when on insert row. UpdatableResultSet.2=Can not call deleteRow() on empty result set. UpdatableResultSet.3=Before start of result set. Can not call deleteRow(). @@ -51,6 +52,7 @@ UpdatableResultSet.34=Updatable result set created, but never updated. You should only create updatable result sets when you want to update/insert/delete values using the updateRow(), deleteRow() and insertRow() methods. UpdatableResultSet.39=Unsupported character encoding ''{0}''. UpdatableResultSet.43=Can not create updatable result sets when there is no currently selected database and MySQL server version < 4.1. +UpdatableResultSet.44=Can not call updateRow() when on insert row. # # Possible re-names @@ -60,7 +62,6 @@ ResultSet.Illegal_value_for_fetch_direction_64=Illegal value for fetch direction ResultSet.Value_must_be_between_0_and_getMaxRows()_66=Value must be between 0 and getMaxRows() ResultSet.Query_generated_no_fields_for_ResultSet_99=Query generated no fields for ResultSet -ResultSet.Cannot_absolute_position_to_row_0_110=Cannot absolute position to row 0 ResultSet.Operation_not_allowed_after_ResultSet_closed_144=Operation not allowed after ResultSet closed ResultSet.Before_start_of_result_set_146=Before start of result set ResultSet.After_end_of_result_set_148=After end of result set @@ -108,7 +109,7 @@ ResultSet.Possible_incomplete_traversal_of_result_set=Possible incomplete traversal of result set. Cursor was left on row {0} of {1} rows when it was closed.\n\nYou should consider re-formulating your query to return only the rows you are interested in using. ResultSet.The_following_columns_were_never_referenced=The following columns were part of the SELECT statement for this result set, but were never referenced: ResultSet.Too_Large_Result_Set=Result set size of {0} rows is larger than \"resultSetSizeThreshold\" of {1} rows. Application may be requesting more data than it is using. Consider reformulating the query. -ResultSet.CostlyConversion=ResultSet type conversion via parsing detected when calling {0} for column {1} (column named '{2}') in table '{3}'{4}\n\nJava class of column type is '{5}', MySQL field type is '{6}'.\n\nTypes that could be converted directly without parsing are:\n{7} +ResultSet.CostlyConversion=ResultSet type conversion via parsing detected when calling {0} for column {1} (column named ''{2}'') in table ''{3}''{4}\n\nJava class of column type is ''{5}'', MySQL field type is ''{6}''.\n\nTypes that could be converted directly without parsing are:\n{7} ResultSet.CostlyConversionCreatedFromQuery= created from query:\n\n ResultSet.Value____173=Value \' @@ -136,7 +137,6 @@ ResultSet.Cannot_convert_value____283=Cannot convert value \' ResultSet.___from_column__284=\' from column ResultSet._)_to_TIMESTAMP._286=\ ) to TIMESTAMP. - CallableStatement.2=Parameter name can not be NULL or zero-length. CallableStatement.3=No parameter named ' CallableStatement.4=' @@ -156,29 +156,24 @@ CallableStatement.16=empty. CallableStatement.21=Parameter CallableStatement.22=\ is not registered as an output parameter - CommunicationsException.2=\ is longer than the server configured value of CommunicationsException.3='wait_timeout' CommunicationsException.4='interactive_timeout' CommunicationsException.5=may or may not be greater than the server-side timeout CommunicationsException.6=(the driver was unable to determine the value of either the CommunicationsException.7='wait_timeout' or 'interactive_timeout' configuration values from CommunicationsException.8=the server. -CommunicationsException.9=The last communications with the server was -CommunicationsException.10=\ seconds ago, which CommunicationsException.11=. You should consider either expiring and/or testing connection validity CommunicationsException.12=before use in your application, increasing the server configured values for client timeouts, CommunicationsException.13=or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. -CommunicationsException.14=The driver was unable to create a connection due to -CommunicationsException.15=an inability to establish the client portion of a socket.\n\n -CommunicationsException.16=This is usually caused by a limit on the number of sockets imposed by -CommunicationsException.17=the operating system. This limit is usually configurable. \n\n -CommunicationsException.18=For Unix-based platforms, see the manual page for the 'ulimit' command. Kernel or system reconfiguration may also be required. -CommunicationsException.19=\n\nFor Windows-based platforms, see Microsoft Knowledge Base Article 196271 (Q196271). -CommunicationsException.19a=The configuration parameter \"localSocketAddress\" has been set to a network interface not available for use by the JVM. +CommunicationsException.TooManyClientConnections=The driver was unable to create a connection due to an inability to establish the client portion of a socket.\n\nThis is usually caused by a limit on the number of sockets imposed by the operating system. This limit is usually configurable. \n\nFor Unix-based platforms, see the manual page for the 'ulimit' command. Kernel or system reconfiguration may also be required.\n\nFor Windows-based platforms, see Microsoft Knowledge Base Article 196271 (Q196271). +CommunicationsException.LocalSocketAddressNotAvailable=The configuration parameter \"localSocketAddress\" has been set to a network interface not available for use by the JVM. CommunicationsException.20=Communications link failure CommunicationsException.21=\ due to underlying exception: CommunicationsException.ClientWasStreaming=Application was streaming results when the connection failed. Consider raising value of 'net_write_timeout' on the server. +CommunicationsException.ServerPacketTimingInfoNoRecv=The last packet sent successfully to the server was {0} milliseconds ago. The driver has not received any packets from the server. +CommunicationsException.ServerPacketTimingInfo=The last packet successfully received from the server was {0} milliseconds ago. The last packet sent successfully to the server was {1} milliseconds ago. +CommunicationsException.TooManyAuthenticationPluginNegotiations=Too many authentication plugin negotiations. NonRegisteringDriver.3=Hostname of MySQL Server NonRegisteringDriver.7=Port number of MySQL Server NonRegisteringDriver.13=Username to authenticate as @@ -225,9 +220,13 @@ ChannelBuffer.1=' Field.12=Unsupported character encoding ' Field.13=' + Blob.0=indexToWriteAt must be >= 1 Blob.1=IO Error while writing bytes to blob Blob.2=Position 'pos' can not be < 1 +Blob.invalidStreamLength=Requested stream length of {2} is out of range, given blob length of {0} and starting position of {1}. +Blob.invalidStreamPos=Position 'pos' can not be < 1 or > blob length. + StringUtils.0=Unsupported character encoding ' StringUtils.1='. StringUtils.5=Unsupported character encoding ' @@ -287,7 +286,8 @@ MysqlIO.22=\ any active result sets before attempting more queries. MysqlIO.23=Can not use streaming results with multiple result statements MysqlIO.25=\ ... (truncated) -MysqlIO.SlowQuery=Slow query (exceeded {0} {1}, duration: {2} {1}): +MysqlIO.SlowQuery=Slow query (exceeded {0} {1}, duration: {2} {1}): +MysqlIO.ServerSlowQuery=The server processing the query has indicated that the query was marked "slow". Nanoseconds=ns Milliseconds=ms MysqlIO.28=Not issuing EXPLAIN for query of size > @@ -347,6 +347,7 @@ MysqlIO.99=\ of MysqlIO.100=\ in binary-encoded result set. MysqlIO.102=, underlying cause: +MysqlIO.103=Unexpected packet length MysqlIO.EOF=Can not read response from server. Expected to read {0} bytes, read {1} bytes before connection was unexpectedly lost. MysqlIO.NoInnoDBStatusFound=No InnoDB status output returned by server. MysqlIO.InnoDBStatusFailed=Couldn't retrieve InnoDB status due to underlying exception: @@ -402,9 +403,9 @@ ServerPreparedStatement.25=Error while reading binary stream: ByteArrayBuffer.0=ByteArrayBuffer has no NIO buffers ByteArrayBuffer.1=Unsupported character encoding ' +ByteArrayBuffer.2=Buffer length is less then "expectedLength" value. AssertionFailedException.0=ASSERT FAILS: Exception AssertionFailedException.1=\ that should not be thrown, was thrown - NotUpdatable.0=Result Set not updatable. NotUpdatable.1=This result set must come from a statement NotUpdatable.2=that was created with a result set type of ResultSet.CONCUR_UPDATABLE, @@ -420,5 +421,272 @@ NotUpdatableReason.6=Result Set not updatable (references unknown primary key {0}). NotUpdatableReason.7=Result Set not updatable (does not reference all primary keys). -InvalidLoadBalanceStrategy=Invalid load balancing strategy '{0}'. -Connection.Connection.BadValueInServerVariables=Invalid value '{1}' for server variable named '{0}', falling back to sane default of '{2}'. +JDBC4Connection.ClientInfoNotImplemented=Configured clientInfoProvider class ''{0}'' does not implement com.mysql.jdbc.JDBC4ClientInfoProvider. + +InvalidLoadBalanceStrategy=Invalid load balancing strategy ''{0}''. +Connection.BadValueInServerVariables=Invalid value ''{1}'' for server variable named ''{0}'', falling back to sane default of ''{2}''. +LoadBalancingConnectionProxy.badValueForRetriesAllDown=Bad value ''{0}'' for property "retriesAllDown". +LoadBalancingConnectionProxy.badValueForLoadBalanceBlacklistTimeout=Bad value ''{0}'' for property "loadBalanceBlacklistTimeout". +LoadBalancingConnectionProxy.badValueForLoadBalanceEnableJMX=Bad value ''{0}'' for property "loadBalanceEnableJMX". +LoadBalancingConnectionProxy.badValueForLoadBalanceAutoCommitStatementThreshold=Invalid numeric value ''{0}'' for property "loadBalanceAutoCommitStatementThreshold". +LoadBalancingConnectionProxy.badValueForLoadBalanceAutoCommitStatementRegex=Bad value ''{0}'' for property "loadBalanceAutoCommitStatementRegex". + +ReplicationConnection.badValueForAllowMasterDownConnections=Bad value ''{0}'' for property "allowMasterDownConnections". + + +Connection.UnableToConnect=Could not create connection to database server. +Connection.UnableToConnectWithRetries=Could not create connection to database server. \ +Attempted reconnect {0} times. Giving up. +Connection.UnexpectedException=Unexpected exception encountered during query. +Connection.UnhandledExceptionDuringShutdown=Unexpected exception during server shutdown. + +Sha256PasswordPlugin.0=Unable to read public key {0} +Sha256PasswordPlugin.1=Unable to close public key file +Sha256PasswordPlugin.2=Public Key Retrieval is not allowed + +# +# ConnectionProperty Categories +# + +ConnectionProperties.categoryConnectionAuthentication=Connection/Authentication +ConnectionProperties.categoryNetworking=Networking +ConnectionProperties.categoryDebuggingProfiling=Debugging/Profiling +ConnectionProperties.categorryHA=High Availability and Clustering +ConnectionProperties.categoryMisc=Miscellaneous +ConnectionProperties.categoryPerformance=Performance Extensions +ConnectionProperties.categorySecurity=Security + +# +# ConnectionProperty Descriptions +# + +ConnectionProperties.loadDataLocal=Should the driver allow use of 'LOAD DATA LOCAL INFILE...' (defaults to 'true'). +ConnectionProperties.allowMasterDownConnections=Should replication-aware driver establish connections to slaves when connection to master servers cannot be established at initial connection? Defaults to 'false', which will cause SQLException when configured master hosts are all unavailable when establishing a new replication-aware Connection. +ConnectionProperties.allowMultiQueries=Allow the use of ';' to delimit multiple queries during one statement (true/false), defaults to 'false', and does not affect the addBatch() and executeBatch() methods, which instead rely on rewriteBatchStatements. +ConnectionProperties.allowNANandINF=Should the driver allow NaN or +/- INF values in PreparedStatement.setDouble()? +ConnectionProperties.allowUrlInLoadLocal=Should the driver allow URLs in 'LOAD DATA LOCAL INFILE' statements? +ConnectionProperties.alwaysSendSetIsolation=Should the driver always communicate with the database when Connection.setTransactionIsolation() is called? If set to false, the driver will only communicate with the database when the requested transaction isolation is different than the whichever is newer, the last value that was set via Connection.setTransactionIsolation(), or the value that was read from the server when the connection was established. Note that useLocalSessionState=true will force the same behavior as alwaysSendSetIsolation=false, regardless of how alwaysSendSetIsolation is set. +ConnectionProperties.autoClosePstmtStreams=Should the driver automatically call .close() on streams/readers passed as arguments via set*() methods? +ConnectionProperties.autoDeserialize=Should the driver automatically detect and de-serialize objects stored in BLOB fields? +ConnectionProperties.autoGenerateTestcaseScript=Should the driver dump the SQL it is executing, including server-side prepared statements to STDERR? +ConnectionProperties.autoReconnect=Should the driver try to re-establish stale and/or dead connections? If enabled the driver will throw an exception for a queries issued on a stale or dead connection, which belong to the current transaction, but will attempt reconnect before the next query issued on the connection in a new transaction. The use of this feature is not recommended, because it has side effects related to session state and data consistency when applications don't handle SQLExceptions properly, and is only designed to be used when you are unable to configure your application to handle SQLExceptions resulting from dead and stale connections properly. Alternatively, as a last option, investigate setting the MySQL server variable "wait_timeout" to a high value, rather than the default of 8 hours. +ConnectionProperties.autoReconnectForPools=Use a reconnection strategy appropriate for connection pools (defaults to 'false') +ConnectionProperties.autoSlowLog=Instead of using slowQueryThreshold* to determine if a query is slow enough to be logged, maintain statistics that allow the driver to determine queries that are outside the 99th percentile? +ConnectionProperties.blobsAreStrings=Should the driver always treat BLOBs as Strings - specifically to work around dubious metadata returned by the server for GROUP BY clauses? +ConnectionProperties.functionsNeverReturnBlobs=Should the driver always treat data from functions returning BLOBs as Strings - specifically to work around dubious metadata returned by the server for GROUP BY clauses? +ConnectionProperties.blobSendChunkSize=Chunk size to use when sending BLOB/CLOBs via ServerPreparedStatements. Note that this value cannot exceed the value of "maxAllowedPacket" and, if that is the case, then this value will be corrected automatically. +ConnectionProperties.cacheCallableStatements=Should the driver cache the parsing stage of CallableStatements +ConnectionProperties.cachePrepStmts=Should the driver cache the parsing stage of PreparedStatements of client-side prepared statements, the "check" for suitability of server-side prepared and server-side prepared statements themselves? +ConnectionProperties.cacheRSMetadata=Should the driver cache ResultSetMetaData for Statements and PreparedStatements? (Req. JDK-1.4+, true/false, default 'false') +ConnectionProperties.cacheServerConfiguration=Should the driver cache the results of 'SHOW VARIABLES' and 'SHOW COLLATION' on a per-URL basis? +ConnectionProperties.callableStmtCacheSize=If 'cacheCallableStmts' is enabled, how many callable statements should be cached? +ConnectionProperties.capitalizeTypeNames=Capitalize type names in DatabaseMetaData? (usually only useful when using WebObjects, true/false, defaults to 'false') +ConnectionProperties.characterEncoding=If 'useUnicode' is set to true, what character encoding should the driver use when dealing with strings? (defaults is to 'autodetect') +ConnectionProperties.characterSetResults=Character set to tell the server to return results as. +ConnectionProperties.clientInfoProvider=The name of a class that implements the com.mysql.jdbc.JDBC4ClientInfoProvider interface in order to support JDBC-4.0's Connection.get/setClientInfo() methods +ConnectionProperties.clobberStreamingResults=This will cause a 'streaming' ResultSet to be automatically closed, and any outstanding data still streaming from the server to be discarded if another query is executed before all the data has been read from the server. +ConnectionProperties.clobCharacterEncoding=The character encoding to use for sending and retrieving TEXT, MEDIUMTEXT and LONGTEXT values instead of the configured connection characterEncoding +ConnectionProperties.compensateOnDuplicateKeyUpdateCounts=Should the driver compensate for the update counts of "ON DUPLICATE KEY" INSERT statements (2 = 1, 0 = 1) when using prepared statements? +ConnectionProperties.connectionCollation=If set, tells the server to use this collation via 'set collation_connection' +ConnectionProperties.connectionLifecycleInterceptors=A comma-delimited list of classes that implement "com.mysql.jdbc.ConnectionLifecycleInterceptor" that should notified of connection lifecycle events (creation, destruction, commit, rollback, setCatalog and setAutoCommit) and potentially alter the execution of these commands. ConnectionLifecycleInterceptors are "stackable", more than one interceptor may be specified via the configuration property as a comma-delimited list, with the interceptors executed in order from left to right. +ConnectionProperties.connectTimeout=Timeout for socket connect (in milliseconds), with 0 being no timeout. Only works on JDK-1.4 or newer. Defaults to '0'. +ConnectionProperties.continueBatchOnError=Should the driver continue processing batch commands if one statement fails. The JDBC spec allows either way (defaults to 'true'). +ConnectionProperties.createDatabaseIfNotExist=Creates the database given in the URL if it doesn't yet exist. Assumes the configured user has permissions to create databases. +ConnectionProperties.defaultFetchSize=The driver will call setFetchSize(n) with this value on all newly-created Statements +ConnectionProperties.useServerPrepStmts=Use server-side prepared statements if the server supports them? +ConnectionProperties.dontTrackOpenResources=The JDBC specification requires the driver to automatically track and close resources, however if your application doesn't do a good job of explicitly calling close() on statements or result sets, this can cause memory leakage. Setting this property to true relaxes this constraint, and can be more memory efficient for some applications. Also the automatic closing of the Statement and current ResultSet in Statement.closeOnCompletion() and Statement.getMoreResults ([Statement.CLOSE_CURRENT_RESULT | Statement.CLOSE_ALL_RESULTS]), respectively, ceases to happen. This property automatically sets holdResultsOpenOverStatementClose=true. +ConnectionProperties.dumpQueriesOnException=Should the driver dump the contents of the query sent to the server in the message for SQLExceptions? +ConnectionProperties.dynamicCalendars=Should the driver retrieve the default calendar when required, or cache it per connection/session? +ConnectionProperties.eliseSetAutoCommit=If using MySQL-4.1 or newer, should the driver only issue 'set autocommit=n' queries when the server's state doesn't match the requested state by Connection.setAutoCommit(boolean)? +ConnectionProperties.emptyStringsConvertToZero=Should the driver allow conversions from empty string fields to numeric values of '0'? +ConnectionProperties.emulateLocators=Should the driver emulate java.sql.Blobs with locators? With this feature enabled, the driver will delay loading the actual Blob data until the one of the retrieval methods (getInputStream(), getBytes(), and so forth) on the blob data stream has been accessed. For this to work, you must use a column alias with the value of the column to the actual name of the Blob. The feature also has the following restrictions: The SELECT that created the result set must reference only one table, the table must have a primary key; the SELECT must alias the original blob column name, specified as a string, to an alternate name; the SELECT must cover all columns that make up the primary key. +ConnectionProperties.emulateUnsupportedPstmts=Should the driver detect prepared statements that are not supported by the server, and replace them with client-side emulated versions? +ConnectionProperties.enablePacketDebug=When enabled, a ring-buffer of 'packetDebugBufferSize' packets will be kept, and dumped when exceptions are thrown in key areas in the driver's code +ConnectionProperties.enableQueryTimeouts=When enabled, query timeouts set via Statement.setQueryTimeout() use a shared java.util.Timer instance for scheduling. Even if the timeout doesn't expire before the query is processed, there will be memory used by the TimerTask for the given timeout which won't be reclaimed until the time the timeout would have expired if it hadn't been cancelled by the driver. High-load environments might want to consider disabling this functionality. +ConnectionProperties.explainSlowQueries=If 'logSlowQueries' is enabled, should the driver automatically issue an 'EXPLAIN' on the server and send the results to the configured log at a WARN level? +ConnectionProperties.failoverReadOnly=When failing over in autoReconnect mode, should the connection be set to 'read-only'? +ConnectionProperties.gatherPerfMetrics=Should the driver gather performance metrics, and report them via the configured logger every 'reportMetricsIntervalMillis' milliseconds? +ConnectionProperties.generateSimpleParameterMetadata=Should the driver generate simplified parameter metadata for PreparedStatements when no metadata is available either because the server couldn't support preparing the statement, or server-side prepared statements are disabled? +ConnectionProperties.holdRSOpenOverStmtClose=Should the driver close result sets on Statement.close() as required by the JDBC specification? +ConnectionProperties.ignoreNonTxTables=Ignore non-transactional table warning for rollback? (defaults to 'false'). +ConnectionProperties.includeInnodbStatusInDeadlockExceptions=Include the output of "SHOW ENGINE INNODB STATUS" in exception messages when deadlock exceptions are detected? +ConnectionProperties.includeThreadDumpInDeadlockExceptions=Include a current Java thread dump in exception messages when deadlock exceptions are detected? +ConnectionProperties.includeThreadNamesAsStatementComment=Include the name of the current thread as a comment visible in "SHOW PROCESSLIST", or in Innodb deadlock dumps, useful in correlation with "includeInnodbStatusInDeadlockExceptions=true" and "includeThreadDumpInDeadlockExceptions=true". +ConnectionProperties.initialTimeout=If autoReconnect is enabled, the initial time to wait between re-connect attempts (in seconds, defaults to '2'). +ConnectionProperties.interactiveClient=Set the CLIENT_INTERACTIVE flag, which tells MySQL to timeout connections based on INTERACTIVE_TIMEOUT instead of WAIT_TIMEOUT +ConnectionProperties.jdbcCompliantTruncation=Should the driver throw java.sql.DataTruncation exceptions when data is truncated as is required by the JDBC specification when connected to a server that supports warnings (MySQL 4.1.0 and newer)? This property has no effect if the server sql-mode includes STRICT_TRANS_TABLES. +ConnectionProperties.largeRowSizeThreshold=What size result set row should the JDBC driver consider "large", and thus use a more memory-efficient way of representing the row internally? +ConnectionProperties.loadBalanceStrategy=If using a load-balanced connection to connect to SQL nodes in a MySQL Cluster/NDB configuration (by using the URL prefix "jdbc:mysql:loadbalance://"), which load balancing algorithm should the driver use: (1) "random" - the driver will pick a random host for each request. This tends to work better than round-robin, as the randomness will somewhat account for spreading loads where requests vary in response time, while round-robin can sometimes lead to overloaded nodes if there are variations in response times across the workload. (2) "bestResponseTime" - the driver will route the request to the host that had the best response time for the previous transaction. +ConnectionProperties.loadBalanceBlacklistTimeout=Time in milliseconds between checks of servers which are unavailable, by controlling how long a server lives in the global blacklist. +ConnectionProperties.loadBalancePingTimeout=Time in milliseconds to wait for ping response from each of load-balanced physical connections when using load-balanced Connection. +ConnectionProperties.loadBalanceValidateConnectionOnSwapServer=Should the load-balanced Connection explicitly check whether the connection is live when swapping to a new physical connection at commit/rollback? +ConnectionProperties.loadBalanceConnectionGroup=Logical group of load-balanced connections within a classloader, used to manage different groups independently. If not specified, live management of load-balanced connections is disabled. +ConnectionProperties.loadBalanceExceptionChecker=Fully-qualified class name of custom exception checker. The class must implement com.mysql.jdbc.LoadBalanceExceptionChecker interface, and is used to inspect SQLExceptions and determine whether they should trigger fail-over to another host in a load-balanced deployment. +ConnectionProperties.loadBalanceSQLStateFailover=Comma-delimited list of SQLState codes used by default load-balanced exception checker to determine whether a given SQLException should trigger failover. The SQLState of a given SQLException is evaluated to determine whether it begins with any value in the comma-delimited list. +ConnectionProperties.loadBalanceSQLExceptionSubclassFailover=Comma-delimited list of classes/interfaces used by default load-balanced exception checker to determine whether a given SQLException should trigger failover. The comparison is done using Class.isInstance(SQLException) using the thrown SQLException. +ConnectionProperties.loadBalanceEnableJMX=Enables JMX-based management of load-balanced connection groups, including live addition/removal of hosts from load-balancing pool. +ConnectionProperties.replicationEnableJMX=Enables JMX-based management of replication connection groups, including live slave promotion, addition of new slaves and removal of master or slave hosts from load-balanced master and slave connection pools. +ConnectionProperties.loadBalanceAutoCommitStatementThreshold=When auto-commit is enabled, the number of statements which should be executed before triggering load-balancing to rebalance. Default value of 0 causes load-balanced connections to only rebalance when exceptions are encountered, or auto-commit is disabled and transactions are explicitly committed or rolled back. +ConnectionProperties.loadBalanceAutoCommitStatementRegex=When load-balancing is enabled for auto-commit statements (via loadBalanceAutoCommitStatementThreshold), the statement counter will only increment when the SQL matches the regular expression. By default, every statement issued matches. + +ConnectionProperties.localSocketAddress=Hostname or IP address given to explicitly configure the interface that the driver will bind the client side of the TCP/IP connection to when connecting. +ConnectionProperties.locatorFetchBufferSize=If 'emulateLocators' is configured to 'true', what size buffer should be used when fetching BLOB data for getBinaryInputStream? +ConnectionProperties.logger=The name of a class that implements \"{0}\" that will be used to log messages to. (default is \"{1}\", which logs to STDERR) +ConnectionProperties.logSlowQueries=Should queries that take longer than 'slowQueryThresholdMillis' be logged? +ConnectionProperties.logXaCommands=Should the driver log XA commands sent by MysqlXaConnection to the server, at the DEBUG level of logging? +ConnectionProperties.maintainTimeStats=Should the driver maintain various internal timers to enable idle time calculations as well as more verbose error messages when the connection to the server fails? Setting this property to false removes at least two calls to System.getCurrentTimeMillis() per query. +ConnectionProperties.maxQuerySizeToLog=Controls the maximum length/size of a query that will get logged when profiling or tracing +ConnectionProperties.maxReconnects=Maximum number of reconnects to attempt if autoReconnect is true, default is '3'. +ConnectionProperties.maxRows=The maximum number of rows to return (0, the default means return all rows). +ConnectionProperties.allVersions=all versions +ConnectionProperties.metadataCacheSize=The number of queries to cache ResultSetMetadata for if cacheResultSetMetaData is set to 'true' (default 50) +ConnectionProperties.netTimeoutForStreamingResults=What value should the driver automatically set the server setting 'net_write_timeout' to when the streaming result sets feature is in use? (value has unit of seconds, the value '0' means the driver will not try and adjust this value) +ConnectionProperties.noAccessToProcedureBodies=When determining procedure parameter types for CallableStatements, and the connected user can't access procedure bodies through "SHOW CREATE PROCEDURE" or select on mysql.proc should the driver instead create basic metadata (all parameters reported as INOUT VARCHARs) instead of throwing an exception? +ConnectionProperties.noDatetimeStringSync=Don't ensure that ResultSet.getDatetimeType().toString().equals(ResultSet.getString()) +ConnectionProperties.noTzConversionForTimeType=Don't convert TIME values using the server timezone if 'useTimezone'='true' +ConnectionProperties.nullCatalogMeansCurrent=When DatabaseMetadataMethods ask for a 'catalog' parameter, does the value null mean use the current catalog? (this is not JDBC-compliant, but follows legacy behavior from earlier versions of the driver) +ConnectionProperties.nullNamePatternMatchesAll=Should DatabaseMetaData methods that accept *pattern parameters treat null the same as '%' (this is not JDBC-compliant, however older versions of the driver accepted this departure from the specification) +ConnectionProperties.packetDebugBufferSize=The maximum number of packets to retain when 'enablePacketDebug' is true +ConnectionProperties.padCharsWithSpace=If a result set column has the CHAR type and the value does not fill the amount of characters specified in the DDL for the column, should the driver pad the remaining characters with space (for ANSI compliance)? +ConnectionProperties.paranoid=Take measures to prevent exposure sensitive information in error messages and clear data structures holding sensitive data when possible? (defaults to 'false') +ConnectionProperties.pedantic=Follow the JDBC spec to the letter. +ConnectionProperties.pinGlobalTxToPhysicalConnection=When using XAConnections, should the driver ensure that operations on a given XID are always routed to the same physical connection? This allows the XAConnection to support "XA START ... JOIN" after "XA END" has been called +ConnectionProperties.populateInsertRowWithDefaultValues=When using ResultSets that are CONCUR_UPDATABLE, should the driver pre-populate the "insert" row with default values from the DDL for the table used in the query so those values are immediately available for ResultSet accessors? This functionality requires a call to the database for metadata each time a result set of this type is created. If disabled (the default), the default values will be populated by the an internal call to refreshRow() which pulls back default values and/or values changed by triggers. +ConnectionProperties.prepStmtCacheSize=If prepared statement caching is enabled, how many prepared statements should be cached? +ConnectionProperties.prepStmtCacheSqlLimit=If prepared statement caching is enabled, what's the largest SQL the driver will cache the parsing for? +ConnectionProperties.processEscapeCodesForPrepStmts=Should the driver process escape codes in queries that are prepared? +ConnectionProperties.profilerEventHandler=Name of a class that implements the interface com.mysql.jdbc.profiler.ProfilerEventHandler that will be used to handle profiling/tracing events. +ConnectionProperties.profileSqlDeprecated=Deprecated, use 'profileSQL' instead. Trace queries and their execution/fetch times on STDERR (true/false) defaults to 'false' +ConnectionProperties.profileSQL=Trace queries and their execution/fetch times to the configured logger (true/false) defaults to 'false' +ConnectionProperties.connectionPropertiesTransform=An implementation of com.mysql.jdbc.ConnectionPropertiesTransform that the driver will use to modify URL properties passed to the driver before attempting a connection +ConnectionProperties.queriesBeforeRetryMaster=Number of queries to issue before falling back to master when failed over (when using multi-host failover). Whichever condition is met first, 'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an attempt to be made to reconnect to the master. Defaults to 50. +ConnectionProperties.reconnectAtTxEnd=If autoReconnect is set to true, should the driver attempt reconnections at the end of every transaction? +ConnectionProperties.relaxAutoCommit=If the version of MySQL the driver connects to does not support transactions, still allow calls to commit(), rollback() and setAutoCommit() (true/false, defaults to 'false')? +ConnectionProperties.reportMetricsIntervalMillis=If 'gatherPerfMetrics' is enabled, how often should they be logged (in ms)? +ConnectionProperties.requireSSL=Require server support of SSL connection if useSSL=true? (defaults to 'false'). +ConnectionProperties.resourceId=A globally unique name that identifies the resource that this datasource or connection is connected to, used for XAResource.isSameRM() when the driver can't determine this value based on hostnames used in the URL +ConnectionProperties.resultSetSizeThreshold=If the usage advisor is enabled, how many rows should a result set contain before the driver warns that it is suspiciously large? +ConnectionProperties.retainStatementAfterResultSetClose=Should the driver retain the Statement reference in a ResultSet after ResultSet.close() has been called. This is not JDBC-compliant after JDBC-4.0. +ConnectionProperties.retriesAllDown=When using loadbalancing, the number of times the driver should cycle through available hosts, attempting to connect. Between cycles, the driver will pause for 250ms if no servers are available. +ConnectionProperties.rewriteBatchedStatements=Should the driver use multiqueries (irregardless of the setting of "allowMultiQueries") as well as rewriting of prepared statements for INSERT into multi-value inserts when executeBatch() is called? Notice that this has the potential for SQL injection if using plain java.sql.Statements and your code doesn't sanitize input correctly. Notice that for prepared statements, server-side prepared statements can not currently take advantage of this rewrite option, and that if you don't specify stream lengths when using PreparedStatement.set*Stream(), the driver won't be able to determine the optimum number of parameters per batch and you might receive an error from the driver that the resultant packet is too large. Statement.getGeneratedKeys() for these rewritten statements only works when the entire batch includes INSERT statements. Please be aware using rewriteBatchedStatements=true with INSERT .. ON DUPLICATE KEY UPDATE that for rewritten statement server returns only one value as sum of all affected (or found) rows in batch and it isn't possible to map it correctly to initial statements; in this case driver returns 0 as a result of each batch statement if total count was 0, and the Statement.SUCCESS_NO_INFO as a result of each batch statement if total count was > 0. +ConnectionProperties.rollbackOnPooledClose=Should the driver issue a rollback() when the logical connection in a pool is closed? +ConnectionProperties.roundRobinLoadBalance=When autoReconnect is enabled, and failoverReadonly is false, should we pick hosts to connect to on a round-robin basis? +ConnectionProperties.runningCTS13=Enables workarounds for bugs in Sun's JDBC compliance testsuite version 1.3 +ConnectionProperties.secondsBeforeRetryMaster=How long should the driver wait, when failed over, before attempting +ConnectionProperties.secondsBeforeRetryMaster.1=to reconnect to the master server? Whichever condition is met first, +ConnectionProperties.secondsBeforeRetryMaster.2='queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an +ConnectionProperties.secondsBeforeRetryMaster.3=attempt to be made to reconnect to the master. Time in seconds, defaults to 30 +ConnectionProperties.selfDestructOnPingSecondsLifetime=If set to a non-zero value, the driver will report close the connection and report failure when Connection.ping() or Connection.isValid(int) is called if the connection's lifetime exceeds this value. +ConnectionProperties.selfDestructOnPingMaxOperations==If set to a non-zero value, the driver will report close the connection and report failure when Connection.ping() or Connection.isValid(int) is called if the connection's count of commands sent to the server exceeds this value. +ConnectionProperties.serverTimezone=Override detection/mapping of timezone. Used when timezone from server doesn't map to Java timezone +ConnectionProperties.sessionVariables=A comma-separated list of name/value pairs to be sent as SET SESSION ... to the server when the driver connects. +ConnectionProperties.slowQueryThresholdMillis=If 'logSlowQueries' is enabled, how long should a query (in ms) before it is logged as 'slow'? +ConnectionProperties.slowQueryThresholdNanos=If 'useNanosForElapsedTime' is set to true, and this property is set to a non-zero value, the driver will use this threshold (in nanosecond units) to determine if a query was slow. +ConnectionProperties.socketFactory=The name of the class that the driver should use for creating socket connections to the server. This class must implement the interface 'com.mysql.jdbc.SocketFactory' and have public no-args constructor. +ConnectionProperties.socketTimeout=Timeout on network socket operations (0, the default means no timeout). +ConnectionProperties.statementInterceptors=A comma-delimited list of classes that implement "com.mysql.jdbc.StatementInterceptor" that should be placed "in between" query execution to influence the results. StatementInterceptors are "chainable", the results returned by the "current" interceptor will be passed on to the next in in the chain, from left-to-right order, as specified in this property. +ConnectionProperties.strictFloatingPoint=Used only in older versions of compliance test +ConnectionProperties.strictUpdates=Should the driver do strict checking (all primary keys selected) of updatable result sets (true, false, defaults to 'true')? +ConnectionProperties.overrideSupportsIEF=Should the driver return "true" for DatabaseMetaData.supportsIntegrityEnhancementFacility() even if the database doesn't support it to workaround applications that require this method to return "true" to signal support of foreign keys, even though the SQL specification states that this facility contains much more than just foreign key support (one such application being OpenOffice)? +ConnectionProperties.tcpNoDelay=If connecting using TCP/IP, should the driver set SO_TCP_NODELAY (disabling the Nagle Algorithm)? +ConnectionProperties.tcpKeepAlive=If connecting using TCP/IP, should the driver set SO_KEEPALIVE? +ConnectionProperties.tcpSoRcvBuf=If connecting using TCP/IP, should the driver set SO_RCV_BUF to the given value? The default value of '0', means use the platform default value for this property) +ConnectionProperties.tcpSoSndBuf=If connecting using TCP/IP, should the driver set SO_SND_BUF to the given value? The default value of '0', means use the platform default value for this property) +ConnectionProperties.tcpTrafficClass=If connecting using TCP/IP, should the driver set traffic class or type-of-service fields ?See the documentation for java.net.Socket.setTrafficClass() for more information. +ConnectionProperties.tinyInt1isBit=Should the driver treat the datatype TINYINT(1) as the BIT type (because the server silently converts BIT -> TINYINT(1) when creating tables)? +ConnectionProperties.traceProtocol=Should trace-level network protocol be logged? +ConnectionProperties.treatUtilDateAsTimestamp=Should the driver treat java.util.Date as a TIMESTAMP for the purposes of PreparedStatement.setObject()? +ConnectionProperties.transformedBitIsBoolean=If the driver converts TINYINT(1) to a different type, should it use BOOLEAN instead of BIT for future compatibility with MySQL-5.0, as MySQL-5.0 has a BIT type? +ConnectionProperties.useCompression=Use zlib compression when communicating with the server (true/false)? Defaults to 'false'. +ConnectionProperties.useConfigs=Load the comma-delimited list of configuration properties before parsing the URL or applying user-specified properties. These configurations are explained in the 'Configurations' of the documentation. +ConnectionProperties.useCursorFetch=If connected to MySQL > 5.0.2, and setFetchSize() > 0 on a statement, should that statement use cursor-based fetching to retrieve rows? +ConnectionProperties.useDynamicCharsetInfo=Should the driver use a per-connection cache of character set information queried from the server when necessary, or use a built-in static mapping that is more efficient, but isn't aware of custom character sets or character sets implemented after the release of the JDBC driver? +ConnectionProperties.useFastIntParsing=Use internal String->Integer conversion routines to avoid excessive object creation? +ConnectionProperties.useFastDateParsing=Use internal String->Date/Time/Timestamp conversion routines to avoid excessive object creation? +ConnectionProperties.useHostsInPrivileges=Add '@hostname' to users in DatabaseMetaData.getColumn/TablePrivileges() (true/false), defaults to 'true'. +ConnectionProperties.useInformationSchema=When connected to MySQL-5.0.7 or newer, should the driver use the INFORMATION_SCHEMA to derive information used by DatabaseMetaData? +ConnectionProperties.useJDBCCompliantTimezoneShift=Should the driver use JDBC-compliant rules when converting TIME/TIMESTAMP/DATETIME values' timezone information for those JDBC arguments which take a java.util.Calendar argument? (Notice that this option is exclusive of the "useTimezone=true" configuration option.) +ConnectionProperties.useLocalSessionState=Should the driver refer to the internal values of autocommit and transaction isolation that are set by Connection.setAutoCommit() and Connection.setTransactionIsolation() and transaction state as maintained by the protocol, rather than querying the database or blindly sending commands to the database for commit() or rollback() method calls? +ConnectionProperties.useLocalTransactionState=Should the driver use the in-transaction state provided by the MySQL protocol to determine if a commit() or rollback() should actually be sent to the database? +ConnectionProperties.useNanosForElapsedTime=For profiling/debugging functionality that measures elapsed time, should the driver try to use nanoseconds resolution if available (JDK >= 1.5)? +ConnectionProperties.useOldAliasMetadataBehavior=Should the driver use the legacy behavior for "AS" clauses on columns and tables, and only return aliases (if any) for ResultSetMetaData.getColumnName() or ResultSetMetaData.getTableName() rather than the original column/table name? In 5.0.x, the default value was true. +ConnectionProperties.useOldUtf8Behavior=Use the UTF-8 behavior the driver did when communicating with 4.0 and older servers +ConnectionProperties.useOnlyServerErrorMessages=Don't prepend 'standard' SQLState error messages to error messages returned by the server. +ConnectionProperties.useReadAheadInput=Use newer, optimized non-blocking, buffered input stream when reading from the server? +ConnectionProperties.useSqlStateCodes=Use SQL Standard state codes instead of 'legacy' X/Open/SQL state codes (true/false), default is 'true' +ConnectionProperties.useSSL=Use SSL when communicating with the server (true/false), defaults to 'false' +ConnectionProperties.useSSPSCompatibleTimezoneShift=If migrating from an environment that was using server-side prepared statements, and the configuration property "useJDBCCompliantTimeZoneShift" set to "true", use compatible behavior when not using server-side prepared statements when sending TIMESTAMP values to the MySQL server. +ConnectionProperties.useStreamLengthsInPrepStmts=Honor stream length parameter in PreparedStatement/ResultSet.setXXXStream() method calls (true/false, defaults to 'true')? +ConnectionProperties.useTimezone=Convert time/date types between client and server timezones (true/false, defaults to 'false')? +ConnectionProperties.ultraDevHack=Create PreparedStatements for prepareCall() when required, because UltraDev is broken and issues a prepareCall() for _all_ statements? (true/false, defaults to 'false') +ConnectionProperties.useUnbufferedInput=Don't use BufferedInputStream for reading data from the server +ConnectionProperties.useUnicode=Should the driver use Unicode character encodings when handling strings? Should only be used when the driver can't determine the character set mapping, or you are trying to 'force' the driver to use a character set that MySQL either doesn't natively support (such as UTF-8), true/false, defaults to 'true' +ConnectionProperties.useUsageAdvisor=Should the driver issue 'usage' warnings advising proper and efficient usage of JDBC and MySQL Connector/J to the log (true/false, defaults to 'false')? +ConnectionProperties.verifyServerCertificate=If "useSSL" is set to "true", should the driver verify the server's certificate? When using this feature, the keystore parameters should be specified by the "clientCertificateKeyStore*" properties, rather than system properties. +ConnectionProperties.yearIsDateType=Should the JDBC driver treat the MySQL type "YEAR" as a java.sql.Date, or as a SHORT? +ConnectionProperties.zeroDateTimeBehavior=What should happen when the driver encounters DATETIME values that are composed entirely of zeros (used by MySQL to represent invalid dates)? Valid values are \"{0}\", \"{1}\" and \"{2}\". +ConnectionProperties.useJvmCharsetConverters=Always use the character encoding routines built into the JVM, rather than using lookup tables for single-byte character sets? +ConnectionProperties.useGmtMillisForDatetimes=Convert between session timezone and GMT before creating Date and Timestamp instances (value of "false" is legacy behavior, "true" leads to more JDBC-compliant behavior. +ConnectionProperties.dumpMetadataOnColumnNotFound=Should the driver dump the field-level metadata of a result set into the exception message when ResultSet.findColumn() fails? +ConnectionProperties.clientCertificateKeyStoreUrl=URL to the client certificate KeyStore (if not specified, use defaults) +ConnectionProperties.trustCertificateKeyStoreUrl=URL to the trusted root certificate KeyStore (if not specified, use defaults) +ConnectionProperties.clientCertificateKeyStoreType=KeyStore type for client certificates (NULL or empty means use the default, which is "JKS". Standard keystore types supported by the JVM are "JKS" and "PKCS12", your environment may have more available depending on what security products are installed and available to the JVM. +ConnectionProperties.clientCertificateKeyStorePassword=Password for the client certificates KeyStore +ConnectionProperties.trustCertificateKeyStoreType=KeyStore type for trusted root certificates (NULL or empty means use the default, which is "JKS". Standard keystore types supported by the JVM are "JKS" and "PKCS12", your environment may have more available depending on what security products are installed and available to the JVM. +ConnectionProperties.trustCertificateKeyStorePassword=Password for the trusted root certificates KeyStore +ConnectionProperties.serverRSAPublicKeyFile=File path to the server RSA public key file for sha256_password authentication. If not specified, the public key will be retrieved from the server. +ConnectionProperties.allowPublicKeyRetrieval=Allows special handshake roundtrip to get server RSA public key directly from server. +ConnectionProperties.Username=The user to connect as +ConnectionProperties.Password=The password to use when connecting +ConnectionProperties.useBlobToStoreUTF8OutsideBMP=Tells the driver to treat [MEDIUM/LONG]BLOB columns as [LONG]VARCHAR columns holding text encoded in UTF-8 that has characters outside the BMP (4-byte encodings), which MySQL server can't handle natively. +ConnectionProperties.utf8OutsideBmpExcludedColumnNamePattern=When "useBlobToStoreUTF8OutsideBMP" is set to "true", column names matching the given regex will still be treated as BLOBs unless they match the regex specified for "utf8OutsideBmpIncludedColumnNamePattern". The regex must follow the patterns used for the java.util.regex package. +ConnectionProperties.utf8OutsideBmpIncludedColumnNamePattern=Used to specify exclusion rules to "utf8OutsideBmpExcludedColumnNamePattern". The regex must follow the patterns used for the java.util.regex package. +ConnectionProperties.useLegacyDatetimeCode=Use code for DATE/TIME/DATETIME/TIMESTAMP handling in result sets and statements that consistently handles timezone conversions from client to server and back again, or use the legacy code for these datatypes that has been in the driver for backwards-compatibility? +ConnectionProperties.useColumnNamesInFindColumn=Prior to JDBC-4.0, the JDBC specification had a bug related to what could be given as a "column name" to ResultSet methods like findColumn(), or getters that took a String property. JDBC-4.0 clarified "column name" to mean the label, as given in an "AS" clause and returned by ResultSetMetaData.getColumnLabel(), and if no AS clause, the column name. Setting this property to "true" will give behavior that is congruent to JDBC-3.0 and earlier versions of the JDBC specification, but which because of the specification bug could give unexpected results. This property is preferred over "useOldAliasMetadataBehavior" unless you need the specific behavior that it provides with respect to ResultSetMetadata. +ConnectionProperties.useAffectedRows=Don't set the CLIENT_FOUND_ROWS flag when connecting to the server (not JDBC-compliant, will break most applications that rely on "found" rows vs. "affected rows" for DML statements), but does cause "correct" update counts from "INSERT ... ON DUPLICATE KEY UPDATE" statements to be returned by the server. +ConnectionProperties.passwordCharacterEncoding=What character encoding is used for passwords? Leaving this set to the default value (null), uses the platform character set, which works for ISO8859_1 (i.e. "latin1") passwords. For passwords in other character encodings, the encoding will have to be specified with this property, as it's not possible for the driver to auto-detect this. +ConnectionProperties.exceptionInterceptors=Comma-delimited list of classes that implement com.mysql.jdbc.ExceptionInterceptor. These classes will be instantiated one per Connection instance, and all SQLExceptions thrown by the driver will be allowed to be intercepted by these interceptors, in a chained fashion, with the first class listed as the head of the chain. +ConnectionProperties.maxAllowedPacket=Maximum allowed packet size to send to server. If not set, the value of system variable 'max_allowed_packet' will be used to initialize this upon connecting. This value will not take effect if set larger than the value of 'max_allowed_packet'. Also, due to an internal dependency with the property "blobSendChunkSize", this setting has a minimum value of "8203" if "useServerPrepStmts" is set to "true". +ConnectionProperties.queryTimeoutKillsConnection=If the timeout given in Statement.setQueryTimeout() expires, should the driver forcibly abort the Connection instead of attempting to abort the query? +ConnectionProperties.authenticationPlugins=Comma-delimited list of classes that implement com.mysql.jdbc.AuthenticationPlugin and which will be used for authentication unless disabled by "disabledAuthenticationPlugins" property. +ConnectionProperties.disabledAuthenticationPlugins=Comma-delimited list of classes implementing com.mysql.jdbc.AuthenticationPlugin or mechanisms, i.e. "mysql_native_password". The authentication plugins or mechanisms listed will not be used for authentication which will fail if it requires one of them. It is an error to disable the default authentication plugin (either the one named by "defaultAuthenticationPlugin" property or the hard-coded one if "defaultAuthenticationPlugin" property is not set). +ConnectionProperties.defaultAuthenticationPlugin=Name of a class implementing com.mysql.jdbc.AuthenticationPlugin which will be used as the default authentication plugin (see below). It is an error to use a class which is not listed in "authenticationPlugins" nor it is one of the built-in plugins. It is an error to set as default a plugin which was disabled with "disabledAuthenticationPlugins" property. It is an error to set this value to null or the empty string (i.e. there must be at least a valid default authentication plugin specified for the connection, meeting all constraints listed above). +ConnectionProperties.parseInfoCacheFactory=Name of a class implementing com.mysql.jdbc.CacheAdapterFactory, which will be used to create caches for the parsed representation of client-side prepared statements. +ConnectionProperties.serverConfigCacheFactory=Name of a class implementing com.mysql.jdbc.CacheAdapterFactory>, which will be used to create caches for MySQL server configuration values +ConnectionProperties.disconnectOnExpiredPasswords=If "disconnectOnExpiredPasswords" is set to "false" and password is expired then server enters "sandbox" mode and sends ERR(08001, ER_MUST_CHANGE_PASSWORD) for all commands that are not needed to set a new password until a new password is set. +ConnectionProperties.connectionAttributes=A comma-delimited list of user-defined key:value pairs (in addition to standard MySQL-defined key:value pairs) to be passed to MySQL Server for display as connection attributes in the PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS table. Example usage: connectionAttributes=key1:value1,key2:value2 This functionality is available for use with MySQL Server version 5.6 or later only. Earlier versions of MySQL Server do not support connection attributes, causing this configuration option will be ignored. Setting connectionAttributes=none will cause connection attribute processing to be bypassed, for situations where Connection creation/initialization speed is critical. +ConnectionProperties.getProceduresReturnsFunctions=Pre-JDBC4 DatabaseMetaData API has only the getProcedures() and getProcedureColumns() methods, so they return metadata info for both stored procedures and functions. JDBC4 was extended with the getFunctions() and getFunctionColumns() methods and the expected behaviours of previous methods are not well defined. For JDBC4 and higher, default 'true' value of the option means that calls of DatabaseMetaData.getProcedures() and DatabaseMetaData.getProcedureColumns() return metadata for both procedures and functions as before, keeping backward compatibility. Setting this property to 'false' decouples Connector/J from its pre-JDBC4 behaviours for DatabaseMetaData.getProcedures() and DatabaseMetaData.getProcedureColumns(), forcing them to return metadata for procedures only. +ConnectionProperties.detectCustomCollations=Should the driver detect custom charsets/collations installed on server (true/false, defaults to 'false'). If this option set to 'true' driver gets actual charsets/collations from server each time connection establishes. This could slow down connection initialization significantly. +# +# Error Messages for Connection Properties +# + +ConnectionProperties.unableToInitDriverProperties=Unable to initialize driver properties due to +ConnectionProperties.unsupportedCharacterEncoding=Unsupported character encoding ''{0}''. +ConnectionProperties.errorNotExpected=Huh? +ConnectionProperties.InternalPropertiesFailure=Internal properties failure +ConnectionProperties.dynamicChangeIsNotAllowed=Dynamic change of ''{0}'' is not allowed. + +TimeUtil.TooGenericTimezoneId=The server timezone value ''{0}'' represents more than one timezone. You must \ +configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a \ +more specifc timezone value if you want to utilize timezone support. The timezones that ''{0}'' maps to are: {1}. + +Connection.exceededConnectionLifetime=Ping or validation failed because configured connection lifetime exceeded. +Connection.badLifecycleInterceptor=Unable to load connection lifecycle interceptor ''{0}''. +MysqlIo.BadStatementInterceptor=Unable to load statement interceptor ''{0}''. +Connection.BadExceptionInterceptor=Unable to load exception interceptor ''{0}''. +Connection.CantDetectLocalConnect=Unable to determine if hostname ''{0}'' is local to this box because of exception, assuming it's not. +Connection.NoMetadataOnSocketFactory=Configured socket factory does not implement SocketMetadata, can not determine whether server is locally-connected, assuming not" +Connection.BadAuthenticationPlugin=Unable to load authentication plugin ''{0}''. +Connection.BadDefaultAuthenticationPlugin=Bad value ''{0}'' for property "defaultAuthenticationPlugin". +Connection.DefaultAuthenticationPluginIsNotListed=defaultAuthenticationPlugin ''{0}'' is not listed in "authenticationPlugins" nor it is one of the built-in plugins. +Connection.BadDisabledAuthenticationPlugin=Can''t disable the default plugin, either remove ''{0}'' from the disabled authentication plugins list, or choose a different default authentication plugin. +Connection.AuthenticationPluginRequiresSSL=SSL connection required for plugin ''{0}''. Check if "useSSL" is set to "true". +Connection.UnexpectedAuthenticationApproval=Unexpected authentication approval: ''{0}'' plugin did not reported "done" state but server has approved connection. +Connection.CantFindCacheFactory=Can not find class ''{0}'' specified by the ''{1}'' configuration property. +Connection.CantLoadCacheFactory=Can not load the cache factory ''{0}'' specified by the ''{1}'' configuration property. +Connection.LoginTimeout=Connection attempt exceeded defined timeout. + +ReplicationConnection.badValueForReplicationEnableJMX=Bad value ''{0}'' for property "replicationEnableJMX". + + Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Messages.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Messages.java (.../Messages.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Messages.java (.../Messages.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.text.MessageFormat; @@ -57,9 +56,12 @@ try { temp = ResourceBundle.getBundle(BUNDLE_NAME); } catch (Throwable t2) { - throw new RuntimeException( + RuntimeException rt = new RuntimeException( "Can't load resource bundle due to underlying exception " + t.toString()); + rt.initCause(t2); + + throw rt; } } finally { RESOURCE_BUNDLE = temp; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MiniAdmin.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MiniAdmin.java (.../MiniAdmin.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MiniAdmin.java (.../MiniAdmin.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,29 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; - import java.util.Properties; /** @@ -54,12 +52,12 @@ public MiniAdmin(java.sql.Connection conn) throws SQLException { if (conn == null) { throw SQLError.createSQLException( - Messages.getString("MiniAdmin.0"), SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$ + Messages.getString("MiniAdmin.0"), SQLError.SQL_STATE_GENERAL_ERROR, null); //$NON-NLS-1$ } if (!(conn instanceof Connection)) { throw SQLError.createSQLException(Messages.getString("MiniAdmin.1"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, ((com.mysql.jdbc.ConnectionImpl)conn).getExceptionInterceptor()); } this.conn = (Connection) conn; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MySQLConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MySQLConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MySQLConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,211 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Calendar; +import java.util.List; +import java.util.Properties; +import java.util.TimeZone; +import java.util.Timer; + +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.profiler.ProfilerEventHandler; + +public interface MySQLConnection extends Connection, ConnectionProperties { + + public boolean isProxySet(); + + void createNewIO(boolean isForReconnect) throws SQLException; + + void dumpTestcaseQuery(String query); + + Connection duplicate() throws SQLException; + + ResultSetInternalMethods execSQL(StatementImpl callingStatement, + String sql, int maxRows, Buffer packet, int resultSetType, + int resultSetConcurrency, boolean streamResults, String catalog, + Field[] cachedMetadata) throws SQLException; + + ResultSetInternalMethods execSQL(StatementImpl callingStatement, + String sql, int maxRows, Buffer packet, int resultSetType, + int resultSetConcurrency, boolean streamResults, String catalog, + Field[] cachedMetadata, boolean isBatch) throws SQLException; + + String extractSqlFromPacket(String possibleSqlQuery, Buffer queryPacket, + int endOfQueryPacketPosition) throws SQLException; + + StringBuffer generateConnectionCommentBlock(StringBuffer buf); + + int getActiveStatementCount(); + + int getAutoIncrementIncrement(); + + CachedResultSetMetaData getCachedMetaData(String sql); + + Calendar getCalendarInstanceForSessionOrNew(); + + Timer getCancelTimer(); + + String getCharacterSetMetadata(); + + SingleByteCharsetConverter getCharsetConverter(String javaEncodingName) + throws SQLException; + + String getCharsetNameForIndex(int charsetIndex) throws SQLException; + + TimeZone getDefaultTimeZone(); + + String getErrorMessageEncoding(); + + ExceptionInterceptor getExceptionInterceptor(); + + String getHost(); + + long getId(); + + long getIdleFor(); + + MysqlIO getIO() throws SQLException; + + Log getLog() throws SQLException; + + int getMaxBytesPerChar(String javaCharsetName) throws SQLException; + + int getMaxBytesPerChar(Integer charsetIndex, String javaCharsetName) throws SQLException; + + java.sql.Statement getMetadataSafeStatement() throws SQLException; + + int getNetBufferLength(); + + Properties getProperties(); + + boolean getRequiresEscapingEncoder(); + + String getServerCharacterEncoding(); + + int getServerMajorVersion(); + + int getServerMinorVersion(); + + int getServerSubMinorVersion(); + + TimeZone getServerTimezoneTZ(); + + String getServerVariable(String variableName); + + String getServerVersion(); + + Calendar getSessionLockedCalendar(); + + String getStatementComment(); + + List getStatementInterceptorsInstances(); + + String getURL(); + + String getUser(); + + Calendar getUtcCalendar(); + + void incrementNumberOfPreparedExecutes(); + + void incrementNumberOfPrepares(); + + void incrementNumberOfResultSetsCreated(); + + void initializeResultsMetadataFromCache(String sql, + CachedResultSetMetaData cachedMetaData, + ResultSetInternalMethods resultSet) throws SQLException; + + void initializeSafeStatementInterceptors() throws SQLException; + + boolean isAbonormallyLongQuery(long millisOrNanos); + + boolean isClientTzUTC(); + + boolean isCursorFetchEnabled() throws SQLException; + + boolean isReadInfoMsgEnabled(); + + public boolean isReadOnly() throws SQLException; + + public boolean isReadOnly(boolean useSessionStatus) throws SQLException; + + boolean isRunningOnJDK13(); + + boolean isServerTzUTC(); + + boolean lowerCaseTableNames(); + + void pingInternal(boolean checkForClosedConnection, int timeoutMillis) + throws SQLException; + + void realClose(boolean calledExplicitly, boolean issueRollback, + boolean skipLocalTeardown, Throwable reason) throws SQLException; + + void recachePreparedStatement(ServerPreparedStatement pstmt) + throws SQLException; + + void decachePreparedStatement(ServerPreparedStatement pstmt) + throws SQLException; + + void registerQueryExecutionTime(long queryTimeMs); + + void registerStatement(Statement stmt); + + void reportNumberOfTablesAccessed(int numTablesAccessed); + + boolean serverSupportsConvertFn() throws SQLException; + + void setProxy(MySQLConnection proxy); + + void setReadInfoMsgEnabled(boolean flag); + + void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException; + + void shutdownServer() throws SQLException; + + boolean storesLowerCaseTableName(); + + void throwConnectionClosedException() throws SQLException; + + void transactionBegun() throws SQLException; + + void transactionCompleted() throws SQLException; + + void unregisterStatement(Statement stmt); + + void unSafeStatementInterceptors() throws SQLException; + + boolean useAnsiQuotedIdentifiers(); + + String getConnectionAttributes() throws SQLException; + + MySQLConnection getLoadBalanceSafeProxy(); + + ProfilerEventHandler getProfilerEventHandlerInstance(); + + void setProfilerEventHandlerInstance(ProfilerEventHandler h); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlDataTruncation.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlDataTruncation.java (.../MysqlDataTruncation.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlDataTruncation.java (.../MysqlDataTruncation.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.DataTruncation; @@ -37,8 +36,12 @@ */ public class MysqlDataTruncation extends DataTruncation { + static final long serialVersionUID = 3263928195256986226L; + private String message; + private int vendorErrorCode; + /** * Creates a new MysqlDataTruncation exception/warning. * @@ -56,19 +59,23 @@ * size actually used */ public MysqlDataTruncation(String message, int index, boolean parameter, - boolean read, int dataSize, int transferSize) { + boolean read, int dataSize, int transferSize, int vendorErrorCode) { super(index, parameter, read, dataSize, transferSize); this.message = message; + this.vendorErrorCode = vendorErrorCode; } + public int getErrorCode() { + return this.vendorErrorCode; + } + /* * (non-Javadoc) * * @see java.lang.Throwable#getMessage() */ public String getMessage() { - // TODO Auto-generated method stub return super.getMessage() + ": " + this.message; //$NON-NLS-1$ } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlDefs.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlDefs.java (.../MysqlDefs.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlDefs.java (.../MysqlDefs.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,29 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.Types; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -37,7 +35,7 @@ * @author Mark Matthews * @version $Id$ */ -final class MysqlDefs { +public final class MysqlDefs { // ~ Static fields/initializers // --------------------------------------------- @@ -81,7 +79,7 @@ static final int FIELD_TYPE_BIT = 16; - static final int FIELD_TYPE_BLOB = 252; + public static final int FIELD_TYPE_BLOB = 252; static final int FIELD_TYPE_DATE = 10; @@ -485,85 +483,85 @@ } } - private static Map mysqlToJdbcTypesMap = new HashMap(); + private static Map mysqlToJdbcTypesMap = new HashMap(); static { - mysqlToJdbcTypesMap.put("BIT", new Integer( + mysqlToJdbcTypesMap.put("BIT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_BIT))); - mysqlToJdbcTypesMap.put("TINYINT", new Integer( + mysqlToJdbcTypesMap.put("TINYINT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_TINY))); - mysqlToJdbcTypesMap.put("SMALLINT", new Integer( + mysqlToJdbcTypesMap.put("SMALLINT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_SHORT))); - mysqlToJdbcTypesMap.put("MEDIUMINT", new Integer( + mysqlToJdbcTypesMap.put("MEDIUMINT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_INT24))); - mysqlToJdbcTypesMap.put("INT", new Integer( + mysqlToJdbcTypesMap.put("INT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_LONG))); - mysqlToJdbcTypesMap.put("INTEGER", new Integer( + mysqlToJdbcTypesMap.put("INTEGER", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_LONG))); - mysqlToJdbcTypesMap.put("BIGINT", new Integer( + mysqlToJdbcTypesMap.put("BIGINT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_LONGLONG))); - mysqlToJdbcTypesMap.put("INT24", new Integer( + mysqlToJdbcTypesMap.put("INT24", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_INT24))); - mysqlToJdbcTypesMap.put("REAL", new Integer( + mysqlToJdbcTypesMap.put("REAL", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_DOUBLE))); - mysqlToJdbcTypesMap.put("FLOAT", new Integer( + mysqlToJdbcTypesMap.put("FLOAT", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_FLOAT))); - mysqlToJdbcTypesMap.put("DECIMAL", new Integer( + mysqlToJdbcTypesMap.put("DECIMAL", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_DECIMAL))); - mysqlToJdbcTypesMap.put("NUMERIC", new Integer( + mysqlToJdbcTypesMap.put("NUMERIC", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_DECIMAL))); - mysqlToJdbcTypesMap.put("DOUBLE", new Integer( + mysqlToJdbcTypesMap.put("DOUBLE", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_DOUBLE))); - mysqlToJdbcTypesMap.put("CHAR", new Integer( + mysqlToJdbcTypesMap.put("CHAR", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_STRING))); - mysqlToJdbcTypesMap.put("VARCHAR", new Integer( + mysqlToJdbcTypesMap.put("VARCHAR", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_VAR_STRING))); - mysqlToJdbcTypesMap.put("DATE", new Integer( + mysqlToJdbcTypesMap.put("DATE", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_DATE))); - mysqlToJdbcTypesMap.put("TIME", new Integer( + mysqlToJdbcTypesMap.put("TIME", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_TIME))); - mysqlToJdbcTypesMap.put("YEAR", new Integer( + mysqlToJdbcTypesMap.put("YEAR", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_YEAR))); - mysqlToJdbcTypesMap.put("TIMESTAMP", new Integer( + mysqlToJdbcTypesMap.put("TIMESTAMP", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_TIMESTAMP))); - mysqlToJdbcTypesMap.put("DATETIME", new Integer( + mysqlToJdbcTypesMap.put("DATETIME", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_DATETIME))); - mysqlToJdbcTypesMap.put("TINYBLOB", new Integer(java.sql.Types.BINARY)); - mysqlToJdbcTypesMap.put("BLOB", new Integer( + mysqlToJdbcTypesMap.put("TINYBLOB", Integer.valueOf(java.sql.Types.BINARY)); + mysqlToJdbcTypesMap.put("BLOB", Integer.valueOf( java.sql.Types.LONGVARBINARY)); - mysqlToJdbcTypesMap.put("MEDIUMBLOB", new Integer( + mysqlToJdbcTypesMap.put("MEDIUMBLOB", Integer.valueOf( java.sql.Types.LONGVARBINARY)); - mysqlToJdbcTypesMap.put("LONGBLOB", new Integer( + mysqlToJdbcTypesMap.put("LONGBLOB", Integer.valueOf( java.sql.Types.LONGVARBINARY)); mysqlToJdbcTypesMap - .put("TINYTEXT", new Integer(java.sql.Types.VARCHAR)); + .put("TINYTEXT", Integer.valueOf(java.sql.Types.VARCHAR)); mysqlToJdbcTypesMap - .put("TEXT", new Integer(java.sql.Types.LONGVARCHAR)); - mysqlToJdbcTypesMap.put("MEDIUMTEXT", new Integer( + .put("TEXT", Integer.valueOf(java.sql.Types.LONGVARCHAR)); + mysqlToJdbcTypesMap.put("MEDIUMTEXT", Integer.valueOf( java.sql.Types.LONGVARCHAR)); - mysqlToJdbcTypesMap.put("LONGTEXT", new Integer( + mysqlToJdbcTypesMap.put("LONGTEXT", Integer.valueOf( java.sql.Types.LONGVARCHAR)); - mysqlToJdbcTypesMap.put("ENUM", new Integer( + mysqlToJdbcTypesMap.put("ENUM", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_ENUM))); - mysqlToJdbcTypesMap.put("SET", new Integer( + mysqlToJdbcTypesMap.put("SET", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_SET))); - mysqlToJdbcTypesMap.put("GEOMETRY", new Integer( + mysqlToJdbcTypesMap.put("GEOMETRY", Integer.valueOf( mysqlToJavaType(FIELD_TYPE_GEOMETRY))); } static final void appendJdbcTypeMappingQuery(StringBuffer buf, String mysqlTypeColumnName) { buf.append("CASE "); - Map typesMap = new HashMap(); + Map typesMap = new HashMap(); typesMap.putAll(mysqlToJdbcTypesMap); - typesMap.put("BINARY", new Integer(Types.BINARY)); - typesMap.put("VARBINARY", new Integer(Types.VARBINARY)); + typesMap.put("BINARY", Integer.valueOf(Types.BINARY)); + typesMap.put("VARBINARY", Integer.valueOf(Types.VARBINARY)); - Iterator mysqlTypes = typesMap.keySet().iterator(); + Iterator mysqlTypes = typesMap.keySet().iterator(); while (mysqlTypes.hasNext()) { - String mysqlTypeName = (String)mysqlTypes.next(); + String mysqlTypeName = mysqlTypes.next(); buf.append(" WHEN "); buf.append(mysqlTypeColumnName); buf.append("='"); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlErrorNumbers.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlErrorNumbers.java (.../MysqlErrorNumbers.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlErrorNumbers.java (.../MysqlErrorNumbers.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -30,611 +29,963 @@ * * @author Mark Matthews * - * @version $Id: MysqlErrorNumbers.java,v 1.1.2.1 2005/05/13 18:58:38 mmatthews - * Exp $ + * @see http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html + * */ public final class MysqlErrorNumbers { - public final static int ER_ABORTING_CONNECTION = 1152; + public final static int ER_ERROR_MESSAGES = 298; + public final static int ER_HASHCHK = 1000; //SQLSTATE: HY000 Message: hashchk + public final static int ER_NISAMCHK = 1001; //SQLSTATE: HY000 Message: isamchk + public final static int ER_NO = 1002; //SQLSTATE: HY000 Message: NO; Used in the construction of other messages. + public final static int ER_YES = 1003; //SQLSTATE: HY000 Message: YES + public final static int ER_CANT_CREATE_FILE = 1004; //SQLSTATE: HY000 Message: Can't create file '%s' (errno: %d - %s) + public final static int ER_CANT_CREATE_TABLE = 1005; //SQLSTATE: HY000 Message: Can't create table '%s' (errno: %d) + public final static int ER_CANT_CREATE_DB = 1006; //SQLSTATE: HY000 Message: Can't create database '%s' (errno: %d) + public final static int ER_DB_CREATE_EXISTS = 1007; //SQLSTATE: HY000 Message: Can't create database '%s'; database exists... + public final static int ER_DB_DROP_EXISTS = 1008; //SQLSTATE: HY000 Message: Can't drop database '%s'; database doesn't exist + public final static int ER_DB_DROP_DELETE = 1009; //SQLSTATE: HY000 Message: Error dropping database (can't delete '%s', errno: %d) + public final static int ER_DB_DROP_RMDIR = 1010; //SQLSTATE: HY000 Message: Error dropping database (can't rmdir '%s', errno: %d) + public final static int ER_CANT_DELETE_FILE = 1011; //SQLSTATE: HY000 Message: Error on delete of '%s' (errno: %d - %s) + public final static int ER_CANT_FIND_SYSTEM_REC = 1012; //SQLSTATE: HY000 Message: Can't read record in system table + public final static int ER_CANT_GET_STAT = 1013; //SQLSTATE: HY000 Message: Can't get status of '%s' (errno: %d - %s) + public final static int ER_CANT_GET_WD = 1014; //SQLSTATE: HY000 Message: Can't get working directory (errno: %d - %s) + public final static int ER_CANT_LOCK = 1015; //SQLSTATE: HY000 Message: Can't lock file (errno: %d - %s) + public final static int ER_CANT_OPEN_FILE = 1016; //SQLSTATE: HY000 Message: Can't open file: '%s' (errno: %d - %s) + public final static int ER_FILE_NOT_FOUND = 1017; //SQLSTATE: HY000 Message: Can't find file: '%s' (errno: %d - %s) + public final static int ER_CANT_READ_DIR = 1018; //SQLSTATE: HY000 Message: Can't read dir of '%s' (errno: %d - %s) + public final static int ER_CANT_SET_WD = 1019; //SQLSTATE: HY000 Message: Can't change dir to '%s' (errno: %d - %s) + public final static int ER_CHECKREAD = 1020; //SQLSTATE: HY000 Message: Record has changed since last read in table '%s' + public final static int ER_DISK_FULL = 1021; //SQLSTATE: HY000 Message: Disk full (%s); waiting for someone to free some space... (errno: %d - %s) + public final static int ER_DUP_KEY = 1022; //SQLSTATE: 23000 Message: Can't write; duplicate key in table '%s' + public final static int ER_ERROR_ON_CLOSE = 1023; //SQLSTATE: HY000 Message: Error on close of '%s' (errno: %d - %s) + public final static int ER_ERROR_ON_READ = 1024; //SQLSTATE: HY000 Message: Error reading file '%s' (errno: %d - %s) + public final static int ER_ERROR_ON_RENAME = 1025; //SQLSTATE: HY000 Message: Error on rename of '%s' to '%s' (errno: %d - %s) + public final static int ER_ERROR_ON_WRITE = 1026; //SQLSTATE: HY000 Message: Error writing file '%s' (errno: %d - %s) + public final static int ER_FILE_USED = 1027; //SQLSTATE: HY000 Message: '%s' is locked against change + public final static int ER_FILSORT_ABORT = 1028; //SQLSTATE: HY000 Message: Sort aborted + public final static int ER_FORM_NOT_FOUND = 1029; //SQLSTATE: HY000 Message: View '%s' doesn't exist for '%s' + public final static int ER_GET_ERRNO = 1030; //SQLSTATE: HY000 Message: Got error %d from storage engine... + public final static int ER_ILLEGAL_HA = 1031; //SQLSTATE: HY000 Message: Table storage engine for '%s' doesn't have this option + public final static int ER_KEY_NOT_FOUND = 1032; //SQLSTATE: HY000 Message: Can't find record in '%s' + public final static int ER_NOT_FORM_FILE = 1033; //SQLSTATE: HY000 Message: Incorrect information in file: '%s' + public final static int ER_NOT_KEYFILE = 1034; //SQLSTATE: HY000 Message: Incorrect key file for table '%s'; try to repair it + public final static int ER_OLD_KEYFILE = 1035; //SQLSTATE: HY000 Message: Old key file for table '%s'; repair it! + public final static int ER_OPEN_AS_READONLY = 1036; //SQLSTATE: HY000 Message: Table '%s' is read only + public final static int ER_OUTOFMEMORY = 1037; //SQLSTATE: HY001 Message: Out of memory; restart server and try again (needed %d bytes) + public final static int ER_OUT_OF_SORTMEMORY = 1038; //SQLSTATE: HY001 Message: Out of sort memory, consider increasing server sort buffer size + public final static int ER_UNEXPECTED_EOF = 1039; //SQLSTATE: HY000 Message: Unexpected EOF found when reading file '%s' (errno: %d - %s) + public final static int ER_CON_COUNT_ERROR = 1040; //SQLSTATE: 08004 Message: Too many connections + public final static int ER_OUT_OF_RESOURCES = 1041; //SQLSTATE: HY000 Message: Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space + public final static int ER_BAD_HOST_ERROR = 1042; //SQLSTATE: 08S01 Message: Can't get hostname for your address + public final static int ER_HANDSHAKE_ERROR = 1043; //SQLSTATE: 08S01 Message: Bad handshake + public final static int ER_DBACCESS_DENIED_ERROR = 1044; //SQLSTATE: 42000 Message: Access denied for user '%s'@'%s' to database '%s' + public final static int ER_ACCESS_DENIED_ERROR = 1045; //SQLSTATE: 28000 Message: Access denied for user '%s'@'%s' (using password: %s) + public final static int ER_NO_DB_ERROR = 1046; //SQLSTATE: 3D000 Message: No database selected + public final static int ER_UNKNOWN_COM_ERROR = 1047; //SQLSTATE: 08S01 Message: Unknown command + public final static int ER_BAD_NULL_ERROR = 1048; //SQLSTATE: 23000 Message: Column '%s' cannot be null + public final static int ER_BAD_DB_ERROR = 1049; //SQLSTATE: 42000 Message: Unknown database '%s' + public final static int ER_TABLE_EXISTS_ERROR = 1050; //SQLSTATE: 42S01 Message: Table '%s' already exists + public final static int ER_BAD_TABLE_ERROR = 1051; //SQLSTATE: 42S02 Message: Unknown table '%s' + public final static int ER_NON_UNIQ_ERROR = 1052; //SQLSTATE: 23000 Message: Column '%s' in %s is ambiguous + public final static int ER_SERVER_SHUTDOWN = 1053; //SQLSTATE: 08S01 Message: Server shutdown in progress + public final static int ER_BAD_FIELD_ERROR = 1054; //SQLSTATE: 42S22 Message: Unknown column '%s' in '%s' + public final static int ER_WRONG_FIELD_WITH_GROUP = 1055; //SQLSTATE: 42000 Message: '%s' isn't in GROUP BY + public final static int ER_WRONG_GROUP_FIELD = 1056; //SQLSTATE: 42000 Message: Can't group on '%s' + public final static int ER_WRONG_SUM_SELECT = 1057; //SQLSTATE: 42000 Message: Statement has sum functions and columns in same statement + public final static int ER_WRONG_VALUE_COUNT = 1058; //SQLSTATE: 21S01 Message: Column count doesn't match value count + public final static int ER_TOO_LONG_IDENT = 1059; //SQLSTATE: 42000 Message: Identifier name '%s' is too long + public final static int ER_DUP_FIELDNAME = 1060; //SQLSTATE: 42S21 Message: Duplicate column name '%s' + public final static int ER_DUP_KEYNAME = 1061; //SQLSTATE: 42000 Message: Duplicate key name '%s' + public final static int ER_DUP_ENTRY = 1062; //SQLSTATE: 23000 Message: Duplicate entry '%s' for key %d + public final static int ER_WRONG_FIELD_SPEC = 1063; //SQLSTATE: 42000 Message: Incorrect column specifier for column '%s' + public final static int ER_PARSE_ERROR = 1064; //SQLSTATE: 42000 Message: %s near '%s' at line %d + public final static int ER_EMPTY_QUERY = 1065; //SQLSTATE: 42000 Message: Query was empty + public final static int ER_NONUNIQ_TABLE = 1066; //SQLSTATE: 42000 Message: Not unique table/alias: '%s' + public final static int ER_INVALID_DEFAULT = 1067; //SQLSTATE: 42000 Message: Invalid default value for '%s' + public final static int ER_MULTIPLE_PRI_KEY = 1068; //SQLSTATE: 42000 Message: Multiple primary key defined + public final static int ER_TOO_MANY_KEYS = 1069; //SQLSTATE: 42000 Message: Too many keys specified; max %d keys allowed + public final static int ER_TOO_MANY_KEY_PARTS = 1070; //SQLSTATE: 42000 Message: Too many key parts specified; max %d parts allowed + public final static int ER_TOO_LONG_KEY = 1071; //SQLSTATE: 42000 Message: Specified key was too long; max key length is %d bytes + public final static int ER_KEY_COLUMN_DOES_NOT_EXITS = 1072; //SQLSTATE: 42000 Message: Key column '%s' doesn't exist in table + public final static int ER_BLOB_USED_AS_KEY = 1073; //SQLSTATE: 42000 Message: BLOB column '%s' can't be used in key specification with the used table type + public final static int ER_TOO_BIG_FIELDLENGTH = 1074; //SQLSTATE: 42000 Message: Column length too big for column '%s' (max = %lu); use BLOB or TEXT instead + public final static int ER_WRONG_AUTO_KEY = 1075; //SQLSTATE: 42000 Message: Incorrect table definition; there can be only one auto column and it must be defined as a key + public final static int ER_READY = 1076; //SQLSTATE: HY000 Message: %s: ready for connections. Version: '%s' socket: '%s' port: %d + public final static int ER_NORMAL_SHUTDOWN = 1077; //SQLSTATE: HY000 Message: %s: Normal shutdown + public final static int ER_GOT_SIGNAL = 1078; //SQLSTATE: HY000 Message: %s: Got signal %d. Aborting! + public final static int ER_SHUTDOWN_COMPLETE = 1079; //SQLSTATE: HY000 Message: %s: Shutdown complete + public final static int ER_FORCING_CLOSE = 1080; //SQLSTATE: 08S01 Message: %s: Forcing close of thread %ld user: '%s' + public final static int ER_IPSOCK_ERROR = 1081; //SQLSTATE: 08S01 Message: Can't create IP socket + public final static int ER_NO_SUCH_INDEX = 1082; //SQLSTATE: 42S12 Message: Table '%s' has no index like the one used in CREATE INDEX; recreate the table + public final static int ER_WRONG_FIELD_TERMINATORS = 1083; //SQLSTATE: 42000 Message: Field separator argument is not what is expected; check the manual + public final static int ER_BLOBS_AND_NO_TERMINATED = 1084; //SQLSTATE: 42000 Message: You can't use fixed rowlength with BLOBs; please use 'fields terminated by' + public final static int ER_TEXTFILE_NOT_READABLE = 1085; //SQLSTATE: HY000 Message: The file '%s' must be in the database directory or be readable by all + public final static int ER_FILE_EXISTS_ERROR = 1086; //SQLSTATE: HY000 Message: File '%s' already exists + public final static int ER_LOAD_INFO = 1087; //SQLSTATE: HY000 Message: Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld + public final static int ER_ALTER_INFO = 1088; //SQLSTATE: HY000 Message: Records: %ld Duplicates: %ld + public final static int ER_WRONG_SUB_KEY = 1089; //SQLSTATE: HY000 Message: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + public final static int ER_CANT_REMOVE_ALL_FIELDS = 1090; //SQLSTATE: 42000 Message: You can't delete all columns with ALTER TABLE; use DROP TABLE instead + public final static int ER_CANT_DROP_FIELD_OR_KEY = 1091; //SQLSTATE: 42000 Message: Can't DROP '%s'; check that column/key exists + public final static int ER_INSERT_INFO = 1092; //SQLSTATE: HY000 Message: Records: %ld Duplicates: %ld Warnings: %ld + public final static int ER_UPDATE_TABLE_USED = 1093; //SQLSTATE: HY000 Message: You can't specify target table '%s' for update in FROM clause + public final static int ER_NO_SUCH_THREAD = 1094; //SQLSTATE: HY000 Message: Unknown thread id: %lu + public final static int ER_KILL_DENIED_ERROR = 1095; //SQLSTATE: HY000 Message: You are not owner of thread %lu + public final static int ER_NO_TABLES_USED = 1096; //SQLSTATE: HY000 Message: No tables used + public final static int ER_TOO_BIG_SET = 1097; //SQLSTATE: HY000 Message: Too many strings for column %s and SET + public final static int ER_NO_UNIQUE_LOGFILE = 1098; //SQLSTATE: HY000 Message: Can't generate a unique log-filename %s.(1-999) + public final static int ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099; //SQLSTATE: HY000 Message: Table '%s' was locked with a READ lock and can't be updated + public final static int ER_TABLE_NOT_LOCKED = 1100; //SQLSTATE: HY000 Message: Table '%s' was not locked with LOCK TABLES + public final static int ER_BLOB_CANT_HAVE_DEFAULT = 1101; //SQLSTATE: 42000 Message: BLOB/TEXT column '%s' can't have a default value + public final static int ER_WRONG_DB_NAME = 1102; //SQLSTATE: 42000 Message: Incorrect database name '%s' + public final static int ER_WRONG_TABLE_NAME = 1103; //SQLSTATE: 42000 Message: Incorrect table name '%s' + public final static int ER_TOO_BIG_SELECT = 1104; //SQLSTATE: 42000 Message: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay + public final static int ER_UNKNOWN_ERROR = 1105; //SQLSTATE: HY000 Message: Unknown error + public final static int ER_UNKNOWN_PROCEDURE = 1106; //SQLSTATE: 42000 Message: Unknown procedure '%s' + public final static int ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107; //SQLSTATE: 42000 Message: Incorrect parameter count to procedure '%s' + public final static int ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108; //SQLSTATE: HY000 Message: Incorrect parameters to procedure '%s' + public final static int ER_UNKNOWN_TABLE = 1109; //SQLSTATE: 42S02 Message: Unknown table '%s' in %s + public final static int ER_FIELD_SPECIFIED_TWICE = 1110; //SQLSTATE: 42000 Message: Column '%s' specified twice + public final static int ER_INVALID_GROUP_FUNC_USE = 1111; //SQLSTATE: HY000 Message: Invalid use of group function + public final static int ER_UNSUPPORTED_EXTENSION = 1112; //SQLSTATE: 42000 Message: Table '%s' uses an extension that doesn't exist in this MySQL version + public final static int ER_TABLE_MUST_HAVE_COLUMNS = 1113; //SQLSTATE: 42000 Message: A table must have at least 1 column + public final static int ER_RECORD_FILE_FULL = 1114; //SQLSTATE: HY000 Message: The table '%s' is full + public final static int ER_UNKNOWN_CHARACTER_SET = 1115; //SQLSTATE: 42000 Message: Unknown character set: '%s' + public final static int ER_TOO_MANY_TABLES = 1116; //SQLSTATE: HY000 Message: Too many tables; MySQL can only use %d tables in a join + public final static int ER_TOO_MANY_FIELDS = 1117; //SQLSTATE: HY000 Message: Too many columns + public final static int ER_TOO_BIG_ROWSIZE = 1118; //SQLSTATE: 42000 Message: Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs + public final static int ER_STACK_OVERRUN = 1119; //SQLSTATE: HY000 Message: Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld --thread_stack=#' to specify a bigger stack if needed + public final static int ER_WRONG_OUTER_JOIN = 1120; //SQLSTATE: 42000 Message: Cross dependency found in OUTER JOIN; examine your ON conditions + public final static int ER_NULL_COLUMN_IN_INDEX = 1121; //SQLSTATE: 42000 Message: Table handler doesn't support NULL in given index. Please change column '%s' to be NOT NULL or use another handler + public final static int ER_CANT_FIND_UDF = 1122; //SQLSTATE: HY000 Message: Can't load function '%s' + public final static int ER_CANT_INITIALIZE_UDF = 1123; //SQLSTATE: HY000 Message: Can't initialize function '%s'; %s + public final static int ER_UDF_NO_PATHS = 1124; //SQLSTATE: HY000 Message: No paths allowed for shared library + public final static int ER_UDF_EXISTS = 1125; //SQLSTATE: HY000 Message: Function '%s' already exists + public final static int ER_CANT_OPEN_LIBRARY = 1126; //SQLSTATE: HY000 Message: Can't open shared library '%s' (errno: %d %s) + public final static int ER_CANT_FIND_DL_ENTRY = 1127; //SQLSTATE: HY000 Message: Can't find symbol '%s' in library + public final static int ER_FUNCTION_NOT_DEFINED = 1128; //SQLSTATE: HY000 Message: Function '%s' is not defined + public final static int ER_HOST_IS_BLOCKED = 1129; //SQLSTATE: HY000 Message: Host '%s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' + public final static int ER_HOST_NOT_PRIVILEGED = 1130; //SQLSTATE: HY000 Message: Host '%s' is not allowed to connect to this MySQL server + public final static int ER_PASSWORD_ANONYMOUS_USER = 1131; //SQLSTATE: 42000 Message: You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords + public final static int ER_PASSWORD_NOT_ALLOWED = 1132; //SQLSTATE: 42000 Message: You must have privileges to update tables in the mysql database to be able to change passwords for others + public final static int ER_PASSWORD_NO_MATCH = 1133; //SQLSTATE: 42000 Message: Can't find any matching row in the user table + public final static int ER_UPDATE_INFO = 1134; //SQLSTATE: HY000 Message: Rows matched: %ld Changed: %ld Warnings: %ld + public final static int ER_CANT_CREATE_THREAD = 1135; //SQLSTATE: HY000 Message: Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug + public final static int ER_WRONG_VALUE_COUNT_ON_ROW = 1136; //SQLSTATE: 21S01 Message: Column count doesn't match value count at row %ld + public final static int ER_CANT_REOPEN_TABLE = 1137; //SQLSTATE: HY000 Message: Can't reopen table: '%s' + public final static int ER_INVALID_USE_OF_NULL = 1138; //SQLSTATE: 22004 Message: Invalid use of NULL value + public final static int ER_REGEXP_ERROR = 1139; //SQLSTATE: 42000 Message: Got error '%s' from regexp + public final static int ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140; //SQLSTATE: 42000 Message: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause + public final static int ER_NONEXISTING_GRANT = 1141; //SQLSTATE: 42000 Message: There is no such grant defined for user '%s' on host '%s' + public final static int ER_TABLEACCESS_DENIED_ERROR = 1142; //SQLSTATE: 42000 Message: %s command denied to user '%s'@'%s' for table '%s' + public final static int ER_COLUMNACCESS_DENIED_ERROR = 1143; //SQLSTATE: 42000 Message: %s command denied to user '%s'@'%s' for column '%s' in table '%s' + public final static int ER_ILLEGAL_GRANT_FOR_TABLE = 1144; //SQLSTATE: 42000 Message: Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used + public final static int ER_GRANT_WRONG_HOST_OR_USER = 1145; //SQLSTATE: 42000 Message: The host or user argument to GRANT is too long + public final static int ER_NO_SUCH_TABLE = 1146; //SQLSTATE: 42S02 Message: Table '%s.%s' doesn't exist + public final static int ER_NONEXISTING_TABLE_GRANT = 1147; //SQLSTATE: 42000 Message: There is no such grant defined for user '%s' on host '%s' on table '%s' + public final static int ER_NOT_ALLOWED_COMMAND = 1148; //SQLSTATE: 42000 Message: The used command is not allowed with this MySQL version + public final static int ER_SYNTAX_ERROR = 1149; //SQLSTATE: 42000 Message: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use + public final static int ER_DELAYED_CANT_CHANGE_LOCK = 1150; //SQLSTATE: HY000 Message: Delayed insert thread couldn't get requested lock for table %s + public final static int ER_TOO_MANY_DELAYED_THREADS = 1151; //SQLSTATE: HY000 Message: Too many delayed threads in use + public final static int ER_ABORTING_CONNECTION = 1152; //SQLSTATE: 08S01 Message: Aborted connection %ld to db: '%s' user: '%s' (%s) + public final static int ER_NET_PACKET_TOO_LARGE = 1153; //SQLSTATE: 08S01 Message: Got a packet bigger than 'max_allowed_packet' bytes + public final static int ER_NET_READ_ERROR_FROM_PIPE = 1154; //SQLSTATE: 08S01 Message: Got a read error from the connection pipe + public final static int ER_NET_FCNTL_ERROR = 1155; //SQLSTATE: 08S01 Message: Got an error from fcntl() + public final static int ER_NET_PACKETS_OUT_OF_ORDER = 1156; //SQLSTATE: 08S01 Message: Got packets out of order + public final static int ER_NET_UNCOMPRESS_ERROR = 1157; //SQLSTATE: 08S01 Message: Couldn't uncompress communication packet + public final static int ER_NET_READ_ERROR = 1158; //SQLSTATE: 08S01 Message: Got an error reading communication packets + public final static int ER_NET_READ_INTERRUPTED = 1159; //SQLSTATE: 08S01 Message: Got timeout reading communication packets + public final static int ER_NET_ERROR_ON_WRITE = 1160; //SQLSTATE: 08S01 Message: Got an error writing communication packets + public final static int ER_NET_WRITE_INTERRUPTED = 1161; //SQLSTATE: 08S01 Message: Got timeout writing communication packets + public final static int ER_TOO_LONG_STRING = 1162; //SQLSTATE: 42000 Message: Result string is longer than 'max_allowed_packet' bytes + public final static int ER_TABLE_CANT_HANDLE_BLOB = 1163; //SQLSTATE: 42000 Message: The used table type doesn't support BLOB/TEXT columns + public final static int ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164; //SQLSTATE: 42000 Message: The used table type doesn't support AUTO_INCREMENT columns + public final static int ER_DELAYED_INSERT_TABLE_LOCKED = 1165; //SQLSTATE: HY000 Message: INSERT DELAYED can't be used with table '%s' because it is locked with LOCK TABLES + public final static int ER_WRONG_COLUMN_NAME = 1166; //SQLSTATE: 42000 Message: Incorrect column name '%s' + public final static int ER_WRONG_KEY_COLUMN = 1167; //SQLSTATE: 42000 Message: The used storage engine can't index column '%s' + public final static int ER_WRONG_MRG_TABLE = 1168; //SQLSTATE: HY000 Message: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist + public final static int ER_DUP_UNIQUE = 1169; //SQLSTATE: 23000 Message: Can't write, because of unique constraint, to table '%s' + public final static int ER_BLOB_KEY_WITHOUT_LENGTH = 1170; //SQLSTATE: 42000 Message: BLOB/TEXT column '%s' used in key specification without a key length + public final static int ER_PRIMARY_CANT_HAVE_NULL = 1171; //SQLSTATE: 42000 Message: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead + public final static int ER_TOO_MANY_ROWS = 1172; //SQLSTATE: 42000 Message: Result consisted of more than one row + public final static int ER_REQUIRES_PRIMARY_KEY = 1173; //SQLSTATE: 42000 Message: This table type requires a primary key + public final static int ER_NO_RAID_COMPILED = 1174; //SQLSTATE: HY000 Message: This version of MySQL is not compiled with RAID support + public final static int ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175; //SQLSTATE: HY000 Message: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column + public final static int ER_KEY_DOES_NOT_EXITS = 1176; //SQLSTATE: 42000 Message: Key '%s' doesn't exist in table '%s' + public final static int ER_CHECK_NO_SUCH_TABLE = 1177; //SQLSTATE: 42000 Message: Can't open table + public final static int ER_CHECK_NOT_IMPLEMENTED = 1178; //SQLSTATE: 42000 Message: The storage engine for the table doesn't support %s + public final static int ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179; //SQLSTATE: 25000 Message: You are not allowed to execute this command in a transaction + public final static int ER_ERROR_DURING_COMMIT = 1180; //SQLSTATE: HY000 Message: Got error %d during COMMIT + public final static int ER_ERROR_DURING_ROLLBACK = 1181; //SQLSTATE: HY000 Message: Got error %d during ROLLBACK + public final static int ER_ERROR_DURING_FLUSH_LOGS = 1182; //SQLSTATE: HY000 Message: Got error %d during FLUSH_LOGS + public final static int ER_ERROR_DURING_CHECKPOINT = 1183; //SQLSTATE: HY000 Message: Got error %d during CHECKPOINT + public final static int ER_NEW_ABORTING_CONNECTION = 1184; //SQLSTATE: 08S01 Message: Aborted connection %ld to db: '%s' user: '%s' host: '%s' (%s) + public final static int ER_DUMP_NOT_IMPLEMENTED = 1185; //SQLSTATE: HY000 Message: The storage engine for the table does not support binary table dump + public final static int ER_FLUSH_MASTER_BINLOG_CLOSED = 1186; //SQLSTATE: HY000 Message: Binlog closed, cannot RESET MASTER + public final static int ER_INDEX_REBUILD = 1187; //SQLSTATE: HY000 Message: Failed rebuilding the index of dumped table '%s' + public final static int ER_MASTER = 1188; //SQLSTATE: HY000 Message: Error from master: '%s' + public final static int ER_MASTER_NET_READ = 1189; //SQLSTATE: 08S01 Message: Net error reading from master + public final static int ER_MASTER_NET_WRITE = 1190; //SQLSTATE: 08S01 Message: Net error writing to master + public final static int ER_FT_MATCHING_KEY_NOT_FOUND = 1191; //SQLSTATE: HY000 Message: Can't find FULLTEXT index matching the column list + public final static int ER_LOCK_OR_ACTIVE_TRANSACTION = 1192; //SQLSTATE: HY000 Message: Can't execute the given command because you have active locked tables or an active transaction + public final static int ER_UNKNOWN_SYSTEM_VARIABLE = 1193; //SQLSTATE: HY000 Message: Unknown system variable '%s' + public final static int ER_CRASHED_ON_USAGE = 1194; //SQLSTATE: HY000 Message: Table '%s' is marked as crashed and should be repaired + public final static int ER_CRASHED_ON_REPAIR = 1195; //SQLSTATE: HY000 Message: Table '%s' is marked as crashed and last (automatic?) repair failed + public final static int ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196; //SQLSTATE: HY000 Message: Some non-transactional changed tables couldn't be rolled back + public final static int ER_TRANS_CACHE_FULL = 1197; //SQLSTATE: HY000 Message: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again + public final static int ER_SLAVE_MUST_STOP = 1198; //SQLSTATE: HY000 Message: This operation cannot be performed with a running slave; run STOP SLAVE first + public final static int ER_SLAVE_NOT_RUNNING = 1199; //SQLSTATE: HY000 Message: This operation requires a running slave; configure slave and do START SLAVE + public final static int ER_BAD_SLAVE = 1200; //SQLSTATE: HY000 Message: The server is not configured as slave; fix in config file or with CHANGE MASTER TO + public final static int ER_MASTER_INFO = 1201; //SQLSTATE: HY000 Message: Could not initialize master info structure; more error messages can be found in the MySQL error log + public final static int ER_SLAVE_THREAD = 1202; //SQLSTATE: HY000 Message: Could not create slave thread; check system resources + public final static int ER_TOO_MANY_USER_CONNECTIONS = 1203; //SQLSTATE: 42000 Message: User %s already has more than 'max_user_connections' active connections + public final static int ER_SET_CONSTANTS_ONLY = 1204; //SQLSTATE: HY000 Message: You may only use constant expressions with SET + public final static int ER_LOCK_WAIT_TIMEOUT = 1205; //SQLSTATE: HY000 Message: Lock wait timeout exceeded; try restarting transaction + public final static int ER_LOCK_TABLE_FULL = 1206; //SQLSTATE: HY000 Message: The total number of locks exceeds the lock table size + public final static int ER_READ_ONLY_TRANSACTION = 1207; //SQLSTATE: 25000 Message: Update locks cannot be acquired during a READ UNCOMMITTED transaction + public final static int ER_DROP_DB_WITH_READ_LOCK = 1208; //SQLSTATE: HY000 Message: DROP DATABASE not allowed while thread is holding global read lock + public final static int ER_CREATE_DB_WITH_READ_LOCK = 1209; //SQLSTATE: HY000 Message: CREATE DATABASE not allowed while thread is holding global read lock + public final static int ER_WRONG_ARGUMENTS = 1210; //SQLSTATE: HY000 Message: Incorrect arguments to %s + public final static int ER_NO_PERMISSION_TO_CREATE_USER = 1211; //SQLSTATE: 42000 Message: '%s'@'%s' is not allowed to create new users + public final static int ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212; //SQLSTATE: HY000 Message: Incorrect table definition; all MERGE tables must be in the same database + public final static int ER_LOCK_DEADLOCK = 1213; //SQLSTATE: 40001 Message: Deadlock found when trying to get lock; try restarting transaction + public final static int ER_TABLE_CANT_HANDLE_FT = 1214; //SQLSTATE: HY000 Message: The used table type doesn't support FULLTEXT indexes + public final static int ER_CANNOT_ADD_FOREIGN = 1215; //SQLSTATE: HY000 Message: Cannot add foreign key constraint + public final static int ER_NO_REFERENCED_ROW = 1216; //SQLSTATE: 23000 Message: Cannot add or update a child row: a foreign key constraint fails + public final static int ER_ROW_IS_REFERENCED = 1217; //SQLSTATE: 23000 Message: Cannot delete or update a parent row: a foreign key constraint fails + public final static int ER_CONNECT_TO_MASTER = 1218; //SQLSTATE: 08S01 Message: Error connecting to master: %s + public final static int ER_QUERY_ON_MASTER = 1219; //SQLSTATE: HY000 Message: Error running query on master: %s + public final static int ER_ERROR_WHEN_EXECUTING_COMMAND = 1220; //SQLSTATE: HY000 Message: Error when executing command %s: %s + public final static int ER_WRONG_USAGE = 1221; //SQLSTATE: HY000 Message: Incorrect usage of %s and %s + public final static int ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222; //SQLSTATE: 21000 Message: The used SELECT statements have a different number of columns + public final static int ER_CANT_UPDATE_WITH_READLOCK = 1223; //SQLSTATE: HY000 Message: Can't execute the query because you have a conflicting read lock + public final static int ER_MIXING_NOT_ALLOWED = 1224; //SQLSTATE: HY000 Message: Mixing of transactional and non-transactional tables is disabled + public final static int ER_DUP_ARGUMENT = 1225; //SQLSTATE: HY000 Message: Option '%s' used twice in statement + public final static int ER_USER_LIMIT_REACHED = 1226; //SQLSTATE: 42000 Message: User '%s' has exceeded the '%s' resource (current value: %ld) + public final static int ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227; //SQLSTATE: 42000 Message: Access denied; you need (at least one of) the %s privilege(s) for this operation + public final static int ER_LOCAL_VARIABLE = 1228; //SQLSTATE: HY000 Message: Variable '%s' is a SESSION variable and can't be used with SET GLOBAL + public final static int ER_GLOBAL_VARIABLE = 1229; //SQLSTATE: HY000 Message: Variable '%s' is a GLOBAL variable and should be set with SET GLOBAL + public final static int ER_NO_DEFAULT = 1230; //SQLSTATE: 42000 Message: Variable '%s' doesn't have a default value + public final static int ER_WRONG_VALUE_FOR_VAR = 1231; //SQLSTATE: 42000 Message: Variable '%s' can't be set to the value of '%s' + public final static int ER_WRONG_TYPE_FOR_VAR = 1232; //SQLSTATE: 42000 Message: Incorrect argument type to variable '%s' + public final static int ER_VAR_CANT_BE_READ = 1233; //SQLSTATE: HY000 Message: Variable '%s' can only be set, not read + public final static int ER_CANT_USE_OPTION_HERE = 1234; //SQLSTATE: 42000 Message: Incorrect usage/placement of '%s' + public final static int ER_NOT_SUPPORTED_YET = 1235; //SQLSTATE: 42000 Message: This version of MySQL doesn't yet support '%s' + public final static int ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236; //SQLSTATE: HY000 Message: Got fatal error %d from master when reading data from binary log: '%s' + public final static int ER_SLAVE_IGNORED_TABLE = 1237; //SQLSTATE: HY000 Message: Slave SQL thread ignored the query because of replicate-*-table rules + public final static int ER_INCORRECT_GLOBAL_LOCAL_VAR = 1238; //SQLSTATE: HY000 Message: Variable '%s' is a %s variable + public final static int ER_WRONG_FK_DEF = 1239; //SQLSTATE: 42000 Message: Incorrect foreign key definition for '%s': %s + public final static int ER_KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240; //SQLSTATE: HY000 Message: Key reference and table reference don't match + public final static int ER_OPERAND_COLUMNS = 1241; //SQLSTATE: 21000 Message: Operand should contain %d column(s) + public final static int ER_SUBQUERY_NO_1_ROW = 1242; //SQLSTATE: 21000 Message: Subquery returns more than 1 row + public final static int ER_UNKNOWN_STMT_HANDLER = 1243; //SQLSTATE: HY000 Message: Unknown prepared statement handler (%.*s) given to %s + public final static int ER_CORRUPT_HELP_DB = 1244; //SQLSTATE: HY000 Message: Help database is corrupt or does not exist + public final static int ER_CYCLIC_REFERENCE = 1245; //SQLSTATE: HY000 Message: Cyclic reference on subqueries + public final static int ER_AUTO_CONVERT = 1246; //SQLSTATE: HY000 Message: Converting column '%s' from %s to %s + public final static int ER_ILLEGAL_REFERENCE = 1247; //SQLSTATE: 42S22 Message: Reference '%s' not supported (%s) + public final static int ER_DERIVED_MUST_HAVE_ALIAS = 1248; //SQLSTATE: 42000 Message: Every derived table must have its own alias + public final static int ER_SELECT_REDUCED = 1249; //SQLSTATE: 01000 Message: Select %u was reduced during optimization + public final static int ER_TABLENAME_NOT_ALLOWED_HERE = 1250; //SQLSTATE: 42000 Message: Table '%s' from one of the SELECTs cannot be used in %s + public final static int ER_NOT_SUPPORTED_AUTH_MODE = 1251; //SQLSTATE: 08004 Message: Client does not support authentication protocol requested by server; consider upgrading MySQL client + public final static int ER_SPATIAL_CANT_HAVE_NULL = 1252; //SQLSTATE: 42000 Message: All parts of a SPATIAL index must be NOT NULL + public final static int ER_COLLATION_CHARSET_MISMATCH = 1253; //SQLSTATE: 42000 Message: COLLATION '%s' is not valid for CHARACTER SET '%s' + public final static int ER_SLAVE_WAS_RUNNING = 1254; //SQLSTATE: HY000 Message: Slave is already running + public final static int ER_SLAVE_WAS_NOT_RUNNING = 1255; //SQLSTATE: HY000 Message: Slave already has been stopped + public final static int ER_TOO_BIG_FOR_UNCOMPRESS = 1256; //SQLSTATE: HY000 Message: Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted) + public final static int ER_ZLIB_Z_MEM_ERROR = 1257; //SQLSTATE: HY000 Message: ZLIB: Not enough memory + public final static int ER_ZLIB_Z_BUF_ERROR = 1258; //SQLSTATE: HY000 Message: ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted) + public final static int ER_ZLIB_Z_DATA_ERROR = 1259; //SQLSTATE: HY000 Message: ZLIB: Input data corrupted + public final static int ER_CUT_VALUE_GROUP_CONCAT = 1260; //SQLSTATE: HY000 Message: Row %u was cut by GROUP_CONCAT() + public final static int ER_WARN_TOO_FEW_RECORDS = 1261; //SQLSTATE: 01000 Message: Row %ld doesn't contain data for all columns + public final static int ER_WARN_TOO_MANY_RECORDS = 1262; //SQLSTATE: 01000 Message: Row %ld was truncated; it contained more data than there were input columns + public final static int ER_WARN_NULL_TO_NOTNULL = 1263; //SQLSTATE: 22004 Message: Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld + public final static int ER_WARN_DATA_OUT_OF_RANGE = 1264; //SQLSTATE: 22003 Message: Out of range value for column '%s' at row %ld + public final static int ER_WARN_DATA_TRUNCATED = 1265; //SQLSTATE: 01000 Message: Data truncated for column '%s' at row %ld + public final static int ER_WARN_USING_OTHER_HANDLER = 1266; //SQLSTATE: HY000 Message: Using storage engine %s for table '%s' + public final static int ER_CANT_AGGREGATE_2COLLATIONS = 1267; //SQLSTATE: HY000 Message: Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s' + public final static int ER_DROP_USER = 1268; //SQLSTATE: HY000 Message: Cannot drop one or more of the requested users + public final static int ER_REVOKE_GRANTS = 1269; //SQLSTATE: HY000 Message: Can't revoke all privileges for one or more of the requested users + public final static int ER_CANT_AGGREGATE_3COLLATIONS = 1270; //SQLSTATE: HY000 Message: Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s' + public final static int ER_CANT_AGGREGATE_NCOLLATIONS = 1271; //SQLSTATE: HY000 Message: Illegal mix of collations for operation '%s' + public final static int ER_VARIABLE_IS_NOT_STRUCT = 1272; //SQLSTATE: HY000 Message: Variable '%s' is not a variable component (can't be used as XXXX.variable_name) + public final static int ER_UNKNOWN_COLLATION = 1273; //SQLSTATE: HY000 Message: Unknown collation: '%s' + public final static int ER_SLAVE_IGNORED_SSL_PARAMS = 1274; //SQLSTATE: HY000 Message: SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started + public final static int ER_SERVER_IS_IN_SECURE_AUTH_MODE = 1275; //SQLSTATE: HY000 Message: Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format + public final static int ER_WARN_FIELD_RESOLVED = 1276; //SQLSTATE: HY000 Message: Field or reference '%s%s%s%s%s' of SELECT #%d was resolved in SELECT #%d + public final static int ER_BAD_SLAVE_UNTIL_COND = 1277; //SQLSTATE: HY000 Message: Incorrect parameter or combination of parameters for START SLAVE UNTIL + public final static int ER_MISSING_SKIP_SLAVE = 1278; //SQLSTATE: HY000 Message: It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart + public final static int ER_UNTIL_COND_IGNORED = 1279; //SQLSTATE: HY000 Message: SQL thread is not to be started so UNTIL options are ignored + public final static int ER_WRONG_NAME_FOR_INDEX = 1280; //SQLSTATE: 42000 Message: Incorrect index name '%s' + public final static int ER_WRONG_NAME_FOR_CATALOG = 1281; //SQLSTATE: 42000 Message: Incorrect catalog name '%s' + public final static int ER_WARN_QC_RESIZE = 1282; //SQLSTATE: HY000 Message: Query cache failed to set size %lu; new query cache size is %lu + public final static int ER_BAD_FT_COLUMN = 1283; //SQLSTATE: HY000 Message: Column '%s' cannot be part of FULLTEXT index + public final static int ER_UNKNOWN_KEY_CACHE = 1284; //SQLSTATE: HY000 Message: Unknown key cache '%s' + public final static int ER_WARN_HOSTNAME_WONT_WORK = 1285; //SQLSTATE: HY000 Message: MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work + public final static int ER_UNKNOWN_STORAGE_ENGINE = 1286; //SQLSTATE: 42000 Message: Unknown storage engine '%s' + public final static int ER_WARN_DEPRECATED_SYNTAX = 1287; //SQLSTATE: HY000 Message: '%s' is deprecated and will be removed in a future release. Please use %s instead + public final static int ER_NON_UPDATABLE_TABLE = 1288; //SQLSTATE: HY000 Message: The target table %s of the %s is not updatable + public final static int ER_FEATURE_DISABLED = 1289; //SQLSTATE: HY000 Message: The '%s' feature is disabled; you need MySQL built with '%s' to have it working + public final static int ER_OPTION_PREVENTS_STATEMENT = 1290; //SQLSTATE: HY000 Message: The MySQL server is running with the %s option so it cannot execute this statement + public final static int ER_DUPLICATED_VALUE_IN_TYPE = 1291; //SQLSTATE: HY000 Message: Column '%s' has duplicated value '%s' in %s + public final static int ER_TRUNCATED_WRONG_VALUE = 1292; //SQLSTATE: 22007 Message: Truncated incorrect %s value: '%s' + public final static int ER_TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293; //SQLSTATE: HY000 Message: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause + public final static int ER_INVALID_ON_UPDATE = 1294; //SQLSTATE: HY000 Message: Invalid ON UPDATE clause for '%s' column + public final static int ER_UNSUPPORTED_PS = 1295; //SQLSTATE: HY000 Message: This command is not supported in the prepared statement protocol yet + public final static int ER_GET_ERRMSG = 1296; //SQLSTATE: HY000 Message: Got error %d '%s' from %s + public final static int ER_GET_TEMPORARY_ERRMSG = 1297; //SQLSTATE: HY000 Message: Got temporary error %d '%s' from %s + public final static int ER_UNKNOWN_TIME_ZONE = 1298; //SQLSTATE: HY000 Message: Unknown or incorrect time zone: '%s' + public final static int ER_WARN_INVALID_TIMESTAMP = 1299; //SQLSTATE: HY000 Message: Invalid TIMESTAMP value in column '%s' at row %ld + public final static int ER_INVALID_CHARACTER_STRING = 1300; //SQLSTATE: HY000 Message: Invalid %s character string: '%s' + public final static int ER_WARN_ALLOWED_PACKET_OVERFLOWED = 1301; //SQLSTATE: HY000 Message: Result of %s() was larger than max_allowed_packet (%ld) - truncated + public final static int ER_CONFLICTING_DECLARATIONS = 1302; //SQLSTATE: HY000 Message: Conflicting declarations: '%s%s' and '%s%s' + public final static int ER_SP_NO_RECURSIVE_CREATE = 1303; //SQLSTATE: 2F003 Message: Can't create a %s from within another stored routine + public final static int ER_SP_ALREADY_EXISTS = 1304; //SQLSTATE: 42000 Message: %s %s already exists + public final static int ER_SP_DOES_NOT_EXIST = 1305; //SQLSTATE: 42000 Message: %s %s does not exist + public final static int ER_SP_DROP_FAILED = 1306; //SQLSTATE: HY000 Message: Failed to DROP %s %s + public final static int ER_SP_STORE_FAILED = 1307; //SQLSTATE: HY000 Message: Failed to CREATE %s %s + public final static int ER_SP_LILABEL_MISMATCH = 1308; //SQLSTATE: 42000 Message: %s with no matching label: %s + public final static int ER_SP_LABEL_REDEFINE = 1309; //SQLSTATE: 42000 Message: Redefining label %s + public final static int ER_SP_LABEL_MISMATCH = 1310; //SQLSTATE: 42000 Message: End-label %s without match + public final static int ER_SP_UNINIT_VAR = 1311; //SQLSTATE: 01000 Message: Referring to uninitialized variable %s + public final static int ER_SP_BADSELECT = 1312; //SQLSTATE: 0A000 Message: PROCEDURE %s can't return a result set in the given context + public final static int ER_SP_BADRETURN = 1313; //SQLSTATE: 42000 Message: RETURN is only allowed in a FUNCTION + public final static int ER_SP_BADSTATEMENT = 1314; //SQLSTATE: 0A000 Message: %s is not allowed in stored procedures + public final static int ER_UPDATE_LOG_DEPRECATED_IGNORED = 1315; //SQLSTATE: 42000 Message: The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored. This option will be removed in MySQL 5.6. + public final static int ER_UPDATE_LOG_DEPRECATED_TRANSLATED = 1316; //SQLSTATE: 42000 Message: The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN. This option will be removed in MySQL 5.6. + public final static int ER_QUERY_INTERRUPTED = 1317; //SQLSTATE: 70100 Message: Query execution was interrupted + public final static int ER_SP_WRONG_NO_OF_ARGS = 1318; //SQLSTATE: 42000 Message: Incorrect number of arguments for %s %s; expected %u, got %u + public final static int ER_SP_COND_MISMATCH = 1319; //SQLSTATE: 42000 Message: Undefined CONDITION: %s + public final static int ER_SP_NORETURN = 1320; //SQLSTATE: 42000 Message: No RETURN found in FUNCTION %s + public final static int ER_SP_NORETURNEND = 1321; //SQLSTATE: 2F005 Message: FUNCTION %s ended without RETURN + public final static int ER_SP_BAD_CURSOR_QUERY = 1322; //SQLSTATE: 42000 Message: Cursor statement must be a SELECT + public final static int ER_SP_BAD_CURSOR_SELECT = 1323; //SQLSTATE: 42000 Message: Cursor SELECT must not have INTO + public final static int ER_SP_CURSOR_MISMATCH = 1324; //SQLSTATE: 42000 Message: Undefined CURSOR: %s + public final static int ER_SP_CURSOR_ALREADY_OPEN = 1325; //SQLSTATE: 24000 Message: Cursor is already open + public final static int ER_SP_CURSOR_NOT_OPEN = 1326; //SQLSTATE: 24000 Message: Cursor is not open + public final static int ER_SP_UNDECLARED_VAR = 1327; //SQLSTATE: 42000 Message: Undeclared variable: %s + public final static int ER_SP_WRONG_NO_OF_FETCH_ARGS = 1328; //SQLSTATE: HY000 Message: Incorrect number of FETCH variables + public final static int ER_SP_FETCH_NO_DATA = 1329; //SQLSTATE: 02000 Message: No data - zero rows fetched, selected, or processed + public final static int ER_SP_DUP_PARAM = 1330; //SQLSTATE: 42000 Message: Duplicate parameter: %s + public final static int ER_SP_DUP_VAR = 1331; //SQLSTATE: 42000 Message: Duplicate variable: %s + public final static int ER_SP_DUP_COND = 1332; //SQLSTATE: 42000 Message: Duplicate condition: %s + public final static int ER_SP_DUP_CURS = 1333; //SQLSTATE: 42000 Message: Duplicate cursor: %s + public final static int ER_SP_CANT_ALTER = 1334; //SQLSTATE: HY000 Message: Failed to ALTER %s %s + public final static int ER_SP_SUBSELECT_NYI = 1335; //SQLSTATE: 0A000 Message: Subquery value not supported + public final static int ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336; //SQLSTATE: 0A000 Message: %s is not allowed in stored function or trigger + public final static int ER_SP_VARCOND_AFTER_CURSHNDLR = 1337; //SQLSTATE: 42000 Message: Variable or condition declaration after cursor or handler declaration + public final static int ER_SP_CURSOR_AFTER_HANDLER = 1338; //SQLSTATE: 42000 Message: Cursor declaration after handler declaration + public final static int ER_SP_CASE_NOT_FOUND = 1339; //SQLSTATE: 20000 Message: Case not found for CASE statement + public final static int ER_FPARSER_TOO_BIG_FILE = 1340; //SQLSTATE: HY000 Message: Configuration file '%s' is too big + public final static int ER_FPARSER_BAD_HEADER = 1341; //SQLSTATE: HY000 Message: Malformed file type header in file '%s' + public final static int ER_FPARSER_EOF_IN_COMMENT = 1342; //SQLSTATE: HY000 Message: Unexpected end of file while parsing comment '%s' + public final static int ER_FPARSER_ERROR_IN_PARAMETER = 1343; //SQLSTATE: HY000 Message: Error while parsing parameter '%s' (line: '%s') + public final static int ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344; //SQLSTATE: HY000 Message: Unexpected end of file while skipping unknown parameter '%s' + public final static int ER_VIEW_NO_EXPLAIN = 1345; //SQLSTATE: HY000 Message: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table + public final static int ER_FRM_UNKNOWN_TYPE = 1346; //SQLSTATE: HY000 Message: File '%s' has unknown type '%s' in its header + public final static int ER_WRONG_OBJECT = 1347; //SQLSTATE: HY000 Message: '%s.%s' is not %s + public final static int ER_NONUPDATEABLE_COLUMN = 1348; //SQLSTATE: HY000 Message: Column '%s' is not updatable + public final static int ER_VIEW_SELECT_DERIVED = 1349; //SQLSTATE: HY000 Message: View's SELECT contains a subquery in the FROM clause + public final static int ER_VIEW_SELECT_CLAUSE = 1350; //SQLSTATE: HY000 Message: View's SELECT contains a '%s' clause + public final static int ER_VIEW_SELECT_VARIABLE = 1351; //SQLSTATE: HY000 Message: View's SELECT contains a variable or parameter + public final static int ER_VIEW_SELECT_TMPTABLE = 1352; //SQLSTATE: HY000 Message: View's SELECT refers to a temporary table '%s' + public final static int ER_VIEW_WRONG_LIST = 1353; //SQLSTATE: HY000 Message: View's SELECT and view's field list have different column counts + public final static int ER_WARN_VIEW_MERGE = 1354; //SQLSTATE: HY000 Message: View merge algorithm can't be used here for now (assumed undefined algorithm) + public final static int ER_WARN_VIEW_WITHOUT_KEY = 1355; //SQLSTATE: HY000 Message: View being updated does not have complete key of underlying table in it + public final static int ER_VIEW_INVALID = 1356; //SQLSTATE: HY000 Message: View '%s.%s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them + public final static int ER_SP_NO_DROP_SP = 1357; //SQLSTATE: HY000 Message: Can't drop or alter a %s from within another stored routine + public final static int ER_SP_GOTO_IN_HNDLR = 1358; //SQLSTATE: HY000 Message: GOTO is not allowed in a stored procedure handler + public final static int ER_TRG_ALREADY_EXISTS = 1359; //SQLSTATE: HY000 Message: Trigger already exists + public final static int ER_TRG_DOES_NOT_EXIST = 1360; //SQLSTATE: HY000 Message: Trigger does not exist + public final static int ER_TRG_ON_VIEW_OR_TEMP_TABLE = 1361; //SQLSTATE: HY000 Message: Trigger's '%s' is view or temporary table + public final static int ER_TRG_CANT_CHANGE_ROW = 1362; //SQLSTATE: HY000 Message: Updating of %s row is not allowed in %strigger + public final static int ER_TRG_NO_SUCH_ROW_IN_TRG = 1363; //SQLSTATE: HY000 Message: There is no %s row in %s trigger + public final static int ER_NO_DEFAULT_FOR_FIELD = 1364; //SQLSTATE: HY000 Message: Field '%s' doesn't have a default value + public final static int ER_DIVISION_BY_ZERO = 1365; //SQLSTATE: 22012 Message: Division by 0 + public final static int ER_TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366; //SQLSTATE: HY000 Message: Incorrect %s value: '%s' for column '%s' at row %ld + public final static int ER_ILLEGAL_VALUE_FOR_TYPE = 1367; //SQLSTATE: 22007 Message: Illegal %s '%s' value found during parsing + public final static int ER_VIEW_NONUPD_CHECK = 1368; //SQLSTATE: HY000 Message: CHECK OPTION on non-updatable view '%s.%s' + public final static int ER_VIEW_CHECK_FAILED = 1369; //SQLSTATE: HY000 Message: CHECK OPTION failed '%s.%s' + public final static int ER_PROCACCESS_DENIED_ERROR = 1370; //SQLSTATE: 42000 Message: %s command denied to user '%s'@'%s' for routine '%s' + public final static int ER_RELAY_LOG_FAIL = 1371; //SQLSTATE: HY000 Message: Failed purging old relay logs: %s + public final static int ER_PASSWD_LENGTH = 1372; //SQLSTATE: HY000 Message: Password hash should be a %d-digit hexadecimal number + public final static int ER_UNKNOWN_TARGET_BINLOG = 1373; //SQLSTATE: HY000 Message: Target log not found in binlog index + public final static int ER_IO_ERR_LOG_INDEX_READ = 1374; //SQLSTATE: HY000 Message: I/O error reading log index file + public final static int ER_BINLOG_PURGE_PROHIBITED = 1375; //SQLSTATE: HY000 Message: Server configuration does not permit binlog purge + public final static int ER_FSEEK_FAIL = 1376; //SQLSTATE: HY000 Message: Failed on fseek() + public final static int ER_BINLOG_PURGE_FATAL_ERR = 1377; //SQLSTATE: HY000 Message: Fatal error during log purge + public final static int ER_LOG_IN_USE = 1378; //SQLSTATE: HY000 Message: A purgeable log is in use, will not purge + public final static int ER_LOG_PURGE_UNKNOWN_ERR = 1379; //SQLSTATE: HY000 Message: Unknown error during log purge + public final static int ER_RELAY_LOG_INIT = 1380; //SQLSTATE: HY000 Message: Failed initializing relay log position: %s + public final static int ER_NO_BINARY_LOGGING = 1381; //SQLSTATE: HY000 Message: You are not using binary logging + public final static int ER_RESERVED_SYNTAX = 1382; //SQLSTATE: HY000 Message: The '%s' syntax is reserved for purposes internal to the MySQL server + public final static int ER_WSAS_FAILED = 1383; //SQLSTATE: HY000 Message: WSAStartup Failed + public final static int ER_DIFF_GROUPS_PROC = 1384; //SQLSTATE: HY000 Message: Can't handle procedures with different groups yet + public final static int ER_NO_GROUP_FOR_PROC = 1385; //SQLSTATE: HY000 Message: Select must have a group with this procedure + public final static int ER_ORDER_WITH_PROC = 1386; //SQLSTATE: HY000 Message: Can't use ORDER clause with this procedure + public final static int ER_LOGGING_PROHIBIT_CHANGING_OF = 1387; //SQLSTATE: HY000 Message: Binary logging and replication forbid changing the global server %s + public final static int ER_NO_FILE_MAPPING = 1388; //SQLSTATE: HY000 Message: Can't map file: %s, errno: %d + public final static int ER_WRONG_MAGIC = 1389; //SQLSTATE: HY000 Message: Wrong magic in %s + public final static int ER_PS_MANY_PARAM = 1390; //SQLSTATE: HY000 Message: Prepared statement contains too many placeholders + public final static int ER_KEY_PART_0 = 1391; //SQLSTATE: HY000 Message: Key part '%s' length cannot be 0 + public final static int ER_VIEW_CHECKSUM = 1392; //SQLSTATE: HY000 Message: View text checksum failed + public final static int ER_VIEW_MULTIUPDATE = 1393; //SQLSTATE: HY000 Message: Can not modify more than one base table through a join view '%s.%s' + public final static int ER_VIEW_NO_INSERT_FIELD_LIST = 1394; //SQLSTATE: HY000 Message: Can not insert into join view '%s.%s' without fields list + public final static int ER_VIEW_DELETE_MERGE_VIEW = 1395; //SQLSTATE: HY000 Message: Can not delete from join view '%s.%s' + public final static int ER_CANNOT_USER = 1396; //SQLSTATE: HY000 Message: Operation %s failed for %s + public final static int ER_XAER_NOTA = 1397; //SQLSTATE: XAE04 Message: XAER_NOTA: Unknown XID + public final static int ER_XAER_INVAL = 1398; //SQLSTATE: XAE05 Message: XAER_INVAL: Invalid arguments (or unsupported command) + public final static int ER_XAER_RMFAIL = 1399; //SQLSTATE: XAE07 Message: XAER_RMFAIL: The command cannot be executed when global transaction is in the %s state + public final static int ER_XAER_OUTSIDE = 1400; //SQLSTATE: XAE09 Message: XAER_OUTSIDE: Some work is done outside global transaction + public final static int ER_XA_RMERR = 1401; + public final static int ER_XA_RBROLLBACK = 1402; //SQLSTATE: XA100 Message: XA_RBROLLBACK: Transaction branch was rolled back + public final static int ER_NONEXISTING_PROC_GRANT = 1403; //SQLSTATE: 42000 Message: There is no such grant defined for user '%s' on host '%s' on routine '%s' + public final static int ER_PROC_AUTO_GRANT_FAIL = 1404; //SQLSTATE: HY000 Message: Failed to grant EXECUTE and ALTER ROUTINE privileges + public final static int ER_PROC_AUTO_REVOKE_FAIL = 1405; //SQLSTATE: HY000 Message: Failed to revoke all privileges to dropped routine + public final static int ER_DATA_TOO_LONG = 1406; //SQLSTATE: 22001 Message: Data too long for column '%s' at row %ld + public final static int ER_SP_BAD_SQLSTATE = 1407; //SQLSTATE: 42000 Message: Bad; //SQLSTATE: '%s' + public final static int ER_STARTUP = 1408; //SQLSTATE: HY000 Message: %s: ready for connections. Version: '%s' socket: '%s' port: %d %s + public final static int ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409; //SQLSTATE: HY000 Message: Can't load value from file with fixed size rows to variable + public final static int ER_CANT_CREATE_USER_WITH_GRANT = 1410; //SQLSTATE: 42000 Message: You are not allowed to create a user with GRANT + public final static int ER_WRONG_VALUE_FOR_TYPE = 1411; //SQLSTATE: HY000 Message: Incorrect %s value: '%s' for function %s + public final static int ER_TABLE_DEF_CHANGED = 1412; //SQLSTATE: HY000 Message: Table definition has changed, please retry transaction + public final static int ER_SP_DUP_HANDLER = 1413; //SQLSTATE: 42000 Message: Duplicate handler declared in the same block + public final static int ER_SP_NOT_VAR_ARG = 1414; //SQLSTATE: 42000 Message: OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger + public final static int ER_SP_NO_RETSET = 1415; //SQLSTATE: 0A000 Message: Not allowed to return a result set from a %s + public final static int ER_CANT_CREATE_GEOMETRY_OBJECT = 1416; //SQLSTATE: 22003 Message: Cannot get geometry object from data you send to the GEOMETRY field + public final static int ER_FAILED_ROUTINE_BREAK_BINLOG = 1417; //SQLSTATE: HY000 Message: A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes + public final static int ER_BINLOG_UNSAFE_ROUTINE = 1418; //SQLSTATE: HY000 Message: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) + public final static int ER_BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419; //SQLSTATE: HY000 Message: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) + public final static int ER_EXEC_STMT_WITH_OPEN_CURSOR = 1420; //SQLSTATE: HY000 Message: You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it. + public final static int ER_STMT_HAS_NO_OPEN_CURSOR = 1421; //SQLSTATE: HY000 Message: The statement (%lu) has no open cursor. + public final static int ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422; //SQLSTATE: HY000 Message: Explicit or implicit commit is not allowed in stored function or trigger. + public final static int ER_NO_DEFAULT_FOR_VIEW_FIELD = 1423; //SQLSTATE: HY000 Message: Field of view '%s.%s' underlying table doesn't have a default value + public final static int ER_SP_NO_RECURSION = 1424; //SQLSTATE: HY000 Message: Recursive stored functions and triggers are not allowed. + public final static int ER_TOO_BIG_SCALE = 1425; //SQLSTATE: 42000 Message: Too big scale %d specified for column '%s'. Maximum is %lu. + public final static int ER_TOO_BIG_PRECISION = 1426; //SQLSTATE: 42000 Message: Too big precision %d specified for column '%s'. Maximum is %lu. + public final static int ER_M_BIGGER_THAN_D = 1427; //SQLSTATE: 42000 Message: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%s'). + public final static int ER_WRONG_LOCK_OF_SYSTEM_TABLE = 1428; //SQLSTATE: HY000 Message: You can't combine write-locking of system tables with other tables or lock types + public final static int ER_CONNECT_TO_FOREIGN_DATA_SOURCE = 1429; //SQLSTATE: HY000 Message: Unable to connect to foreign data source: %s + public final static int ER_QUERY_ON_FOREIGN_DATA_SOURCE = 1430; //SQLSTATE: HY000 Message: There was a problem processing the query on the foreign data source. Data source error: %s + public final static int ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431; //SQLSTATE: HY000 Message: The foreign data source you are trying to reference does not exist. Data source error: %s + public final static int ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432; //SQLSTATE: HY000 Message: Can't create federated table. The data source connection string '%s' is not in the correct format + public final static int ER_FOREIGN_DATA_STRING_INVALID = 1433; //SQLSTATE: HY000 Message: The data source connection string '%s' is not in the correct format + public final static int ER_CANT_CREATE_FEDERATED_TABLE = 1434; //SQLSTATE: HY000 Message: Can't create federated table. Foreign data src error: %s + public final static int ER_TRG_IN_WRONG_SCHEMA = 1435; //SQLSTATE: HY000 Message: Trigger in wrong schema + public final static int ER_STACK_OVERRUN_NEED_MORE = 1436; //SQLSTATE: HY000 Message: Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld --thread_stack=#' to specify a bigger stack. + public final static int ER_TOO_LONG_BODY = 1437; //SQLSTATE: 42000 Message: Routine body for '%s' is too long + public final static int ER_WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438; //SQLSTATE: HY000 Message: Cannot drop default keycache + public final static int ER_TOO_BIG_DISPLAYWIDTH = 1439; //SQLSTATE: 42000 Message: Display width out of range for column '%s' (max = %lu) + public final static int ER_XAER_DUPID = 1440; //SQLSTATE: XAE08 Message: XAER_DUPID: The XID already exists + public final static int ER_DATETIME_FUNCTION_OVERFLOW = 1441; //SQLSTATE: 22008 Message: Datetime function: %s field overflow + public final static int ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442; //SQLSTATE: HY000 Message: Can't update table '%s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. + public final static int ER_VIEW_PREVENT_UPDATE = 1443; //SQLSTATE: HY000 Message: The definition of table '%s' prevents operation %s on table '%s'. + public final static int ER_PS_NO_RECURSION = 1444; //SQLSTATE: HY000 Message: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner + public final static int ER_SP_CANT_SET_AUTOCOMMIT = 1445; //SQLSTATE: HY000 Message: Not allowed to set autocommit from a stored function or trigger + public final static int ER_MALFORMED_DEFINER = 1446; //SQLSTATE: HY000 Message: Definer is not fully qualified + public final static int ER_VIEW_FRM_NO_USER = 1447; //SQLSTATE: HY000 Message: View '%s'.'%s' has no definer information (old table format). Current user is used as definer. Please recreate the view! + public final static int ER_VIEW_OTHER_USER = 1448; //SQLSTATE: HY000 Message: You need the SUPER privilege for creation view with '%s'@'%s' definer + public final static int ER_NO_SUCH_USER = 1449; //SQLSTATE: HY000 Message: The user specified as a definer ('%s'@'%s') does not exist + public final static int ER_FORBID_SCHEMA_CHANGE = 1450; //SQLSTATE: HY000 Message: Changing schema from '%s' to '%s' is not allowed. + public final static int ER_ROW_IS_REFERENCED_2 = 1451; //SQLSTATE: 23000 Message: Cannot delete or update a parent row: a foreign key constraint fails (%s) + public final static int ER_NO_REFERENCED_ROW_2 = 1452; //SQLSTATE: 23000 Message: Cannot add or update a child row: a foreign key constraint fails (%s) + public final static int ER_SP_BAD_VAR_SHADOW = 1453; //SQLSTATE: 42000 Message: Variable '%s' must be quoted with `...`, or renamed + public final static int ER_TRG_NO_DEFINER = 1454; //SQLSTATE: HY000 Message: No definer attribute for trigger '%s'.'%s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. + public final static int ER_OLD_FILE_FORMAT = 1455; //SQLSTATE: HY000 Message: '%s' has an old format, you should re-create the '%s' object(s) + public final static int ER_SP_RECURSION_LIMIT = 1456; //SQLSTATE: HY000 Message: Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %s + public final static int ER_SP_PROC_TABLE_CORRUPT = 1457; //SQLSTATE: HY000 Message: Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d) + public final static int ER_SP_WRONG_NAME = 1458; //SQLSTATE: 42000 Message: Incorrect routine name '%s' + public final static int ER_TABLE_NEEDS_UPGRADE = 1459; //SQLSTATE: HY000 Message: Table upgrade required. Please do "REPAIR TABLE `%s`" or dump/reload to fix it! + public final static int ER_SP_NO_AGGREGATE = 1460; //SQLSTATE: 42000 Message: AGGREGATE is not supported for stored functions + public final static int ER_MAX_PREPARED_STMT_COUNT_REACHED = 1461; //SQLSTATE: 42000 Message: Can't create more than max_prepared_stmt_count statements (current value: %lu) + public final static int ER_VIEW_RECURSIVE = 1462; //SQLSTATE: HY000 Message: `%s`.`%s` contains view recursion + public final static int ER_NON_GROUPING_FIELD_USED = 1463; //SQLSTATE: 42000 Message: non-grouping field '%s' is used in %s clause + public final static int ER_TABLE_CANT_HANDLE_SPKEYS = 1464; //SQLSTATE: HY000 Message: The used table type doesn't support SPATIAL indexes + public final static int ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA = 1465; //SQLSTATE: HY000 Message: Triggers can not be created on system tables + public final static int ER_REMOVED_SPACES = 1466; //SQLSTATE: HY000 Message: Leading spaces are removed from name '%s' + public final static int ER_AUTOINC_READ_FAILED = 1467; //SQLSTATE: HY000 Message: Failed to read auto-increment value from storage engine + public final static int ER_USERNAME = 1468; //SQLSTATE: HY000 Message: user name + public final static int ER_HOSTNAME = 1469; //SQLSTATE: HY000 Message: host name + public final static int ER_WRONG_STRING_LENGTH = 1470; //SQLSTATE: HY000 Message: String '%s' is too long for %s (should be no longer than %d) + public final static int ER_NON_INSERTABLE_TABLE = 1471; //SQLSTATE: HY000 Message: The target table %s of the %s is not insertable-into + public final static int ER_ADMIN_WRONG_MRG_TABLE = 1472; //SQLSTATE: HY000 Message: Table '%s' is differently defined or of non-MyISAM type or doesn't exist + public final static int ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT = 1473; //SQLSTATE: HY000 Message: Too high level of nesting for select + public final static int ER_NAME_BECOMES_EMPTY = 1474; //SQLSTATE: HY000 Message: Name '%s' has become '' + public final static int ER_AMBIGUOUS_FIELD_TERM = 1475; //SQLSTATE: HY000 Message: First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY + public final static int ER_FOREIGN_SERVER_EXISTS = 1476; //SQLSTATE: HY000 Message: The foreign server, %s, you are trying to create already exists. + public final static int ER_FOREIGN_SERVER_DOESNT_EXIST = 1477; //SQLSTATE: HY000 Message: The foreign server name you are trying to reference does not exist. Data source error: %s + public final static int ER_ILLEGAL_HA_CREATE_OPTION = 1478; //SQLSTATE: HY000 Message: Table storage engine '%s' does not support the create option '%s' + public final static int ER_PARTITION_REQUIRES_VALUES_ERROR = 1479; //SQLSTATE: HY000 Message: Syntax error: %s PARTITIONING requires definition of VALUES %s for each partition + public final static int ER_PARTITION_WRONG_VALUES_ERROR = 1480; //SQLSTATE: HY000 Message: Only %s PARTITIONING can use VALUES %s in partition definition + public final static int ER_PARTITION_MAXVALUE_ERROR = 1481; //SQLSTATE: HY000 Message: MAXVALUE can only be used in last partition definition + public final static int ER_PARTITION_SUBPARTITION_ERROR = 1482; //SQLSTATE: HY000 Message: Subpartitions can only be hash partitions and by key + public final static int ER_PARTITION_SUBPART_MIX_ERROR = 1483; //SQLSTATE: HY000 Message: Must define subpartitions on all partitions if on one partition + public final static int ER_PARTITION_WRONG_NO_PART_ERROR = 1484; //SQLSTATE: HY000 Message: Wrong number of partitions defined, mismatch with previous setting + public final static int ER_PARTITION_WRONG_NO_SUBPART_ERROR = 1485; //SQLSTATE: HY000 Message: Wrong number of subpartitions defined, mismatch with previous setting + public final static int ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR = 1486; //SQLSTATE: HY000 Message: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed + public final static int ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR = 1487; //SQLSTATE: HY000 Message: Expression in RANGE/LIST VALUES must be constant + public final static int ER_FIELD_NOT_FOUND_PART_ERROR = 1488; //SQLSTATE: HY000 Message: Field in list of fields for partition function not found in table + public final static int ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR = 1489; //SQLSTATE: HY000 Message: List of fields is only allowed in KEY partitions + public final static int ER_INCONSISTENT_PARTITION_INFO_ERROR = 1490; //SQLSTATE: HY000 Message: The partition info in the frm file is not consistent with what can be written into the frm file + public final static int ER_PARTITION_FUNC_NOT_ALLOWED_ERROR = 1491; //SQLSTATE: HY000 Message: The %s function returns the wrong type + public final static int ER_PARTITIONS_MUST_BE_DEFINED_ERROR = 1492; //SQLSTATE: HY000 Message: For %s partitions each partition must be defined + public final static int ER_RANGE_NOT_INCREASING_ERROR = 1493; //SQLSTATE: HY000 Message: VALUES LESS THAN value must be strictly increasing for each partition + public final static int ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR = 1494; //SQLSTATE: HY000 Message: VALUES value must be of same type as partition function + public final static int ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR = 1495; //SQLSTATE: HY000 Message: Multiple definition of same constant in list partitioning + public final static int ER_PARTITION_ENTRY_ERROR = 1496; //SQLSTATE: HY000 Message: Partitioning can not be used stand-alone in query + public final static int ER_MIX_HANDLER_ERROR = 1497; //SQLSTATE: HY000 Message: The mix of handlers in the partitions is not allowed in this version of MySQL + public final static int ER_PARTITION_NOT_DEFINED_ERROR = 1498; //SQLSTATE: HY000 Message: For the partitioned engine it is necessary to define all %s + public final static int ER_TOO_MANY_PARTITIONS_ERROR = 1499; //SQLSTATE: HY000 Message: Too many partitions (including subpartitions) were defined + public final static int ER_SUBPARTITION_ERROR = 1500; //SQLSTATE: HY000 Message: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning + public final static int ER_CANT_CREATE_HANDLER_FILE = 1501; //SQLSTATE: HY000 Message: Failed to create specific handler file + public final static int ER_BLOB_FIELD_IN_PART_FUNC_ERROR = 1502; //SQLSTATE: HY000 Message: A BLOB field is not allowed in partition function + public final static int ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF = 1503; //SQLSTATE: HY000 Message: A %s must include all columns in the table's partitioning function + public final static int ER_NO_PARTS_ERROR = 1504; //SQLSTATE: HY000 Message: Number of %s = 0 is not an allowed value + public final static int ER_PARTITION_MGMT_ON_NONPARTITIONED = 1505; //SQLSTATE: HY000 Message: Partition management on a not partitioned table is not possible + public final static int ER_FOREIGN_KEY_ON_PARTITIONED = 1506; //SQLSTATE: HY000 Message: Foreign key clause is not yet supported in conjunction with partitioning + public final static int ER_DROP_PARTITION_NON_EXISTENT = 1507; //SQLSTATE: HY000 Message: Error in list of partitions to %s + public final static int ER_DROP_LAST_PARTITION = 1508; //SQLSTATE: HY000 Message: Cannot remove all partitions, use DROP TABLE instead + public final static int ER_COALESCE_ONLY_ON_HASH_PARTITION = 1509; //SQLSTATE: HY000 Message: COALESCE PARTITION can only be used on HASH/KEY partitions + public final static int ER_REORG_HASH_ONLY_ON_SAME_NO = 1510; //SQLSTATE: HY000 Message: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers + public final static int ER_REORG_NO_PARAM_ERROR = 1511; //SQLSTATE: HY000 Message: REORGANIZE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs + public final static int ER_ONLY_ON_RANGE_LIST_PARTITION = 1512; //SQLSTATE: HY000 Message: %s PARTITION can only be used on RANGE/LIST partitions + public final static int ER_ADD_PARTITION_SUBPART_ERROR = 1513; //SQLSTATE: HY000 Message: Trying to Add partition(s) with wrong number of subpartitions + public final static int ER_ADD_PARTITION_NO_NEW_PARTITION = 1514; //SQLSTATE: HY000 Message: At least one partition must be added + public final static int ER_COALESCE_PARTITION_NO_PARTITION = 1515; //SQLSTATE: HY000 Message: At least one partition must be coalesced + public final static int ER_REORG_PARTITION_NOT_EXIST = 1516; //SQLSTATE: HY000 Message: More partitions to reorganize than there are partitions + public final static int ER_SAME_NAME_PARTITION = 1517; //SQLSTATE: HY000 Message: Duplicate partition name %s + public final static int ER_NO_BINLOG_ERROR = 1518; //SQLSTATE: HY000 Message: It is not allowed to shut off binlog on this command + public final static int ER_CONSECUTIVE_REORG_PARTITIONS = 1519; //SQLSTATE: HY000 Message: When reorganizing a set of partitions they must be in consecutive order + public final static int ER_REORG_OUTSIDE_RANGE = 1520; //SQLSTATE: HY000 Message: Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range + public final static int ER_PARTITION_FUNCTION_FAILURE = 1521; //SQLSTATE: HY000 Message: Partition function not supported in this version for this handler + public final static int ER_PART_STATE_ERROR = 1522; //SQLSTATE: HY000 Message: Partition state cannot be defined from CREATE/ALTER TABLE + public final static int ER_LIMITED_PART_RANGE = 1523; //SQLSTATE: HY000 Message: The %s handler only supports 32 bit integers in VALUES + public final static int ER_PLUGIN_IS_NOT_LOADED = 1524; //SQLSTATE: HY000 Message: Plugin '%s' is not loaded + public final static int ER_WRONG_VALUE = 1525; //SQLSTATE: HY000 Message: Incorrect %s value: '%s' + public final static int ER_NO_PARTITION_FOR_GIVEN_VALUE = 1526; //SQLSTATE: HY000 Message: Table has no partition for value %s + public final static int ER_FILEGROUP_OPTION_ONLY_ONCE = 1527; //SQLSTATE: HY000 Message: It is not allowed to specify %s more than once + public final static int ER_CREATE_FILEGROUP_FAILED = 1528; //SQLSTATE: HY000 Message: Failed to create %s + public final static int ER_DROP_FILEGROUP_FAILED = 1529; //SQLSTATE: HY000 Message: Failed to drop %s + public final static int ER_TABLESPACE_AUTO_EXTEND_ERROR = 1530; //SQLSTATE: HY000 Message: The handler doesn't support autoextend of tablespaces + public final static int ER_WRONG_SIZE_NUMBER = 1531; //SQLSTATE: HY000 Message: A size parameter was incorrectly specified, either number or on the form 10M + public final static int ER_SIZE_OVERFLOW_ERROR = 1532; //SQLSTATE: HY000 Message: The size number was correct but we don't allow the digit part to be more than 2 billion + public final static int ER_ALTER_FILEGROUP_FAILED = 1533; //SQLSTATE: HY000 Message: Failed to alter: %s + public final static int ER_BINLOG_ROW_LOGGING_FAILED = 1534; //SQLSTATE: HY000 Message: Writing one row to the row-based binary log failed + public final static int ER_BINLOG_ROW_WRONG_TABLE_DEF = 1535; //SQLSTATE: HY000 Message: Table definition on master and slave does not match: %s + public final static int ER_BINLOG_ROW_RBR_TO_SBR = 1536; //SQLSTATE: HY000 Message: Slave running with --log-slave-updates must use row-based binary logging to be able to replicate row-based binary log events + public final static int ER_EVENT_ALREADY_EXISTS = 1537; //SQLSTATE: HY000 Message: Event '%s' already exists + public final static int ER_EVENT_STORE_FAILED = 1538; //SQLSTATE: HY000 Message: Failed to store event %s. Error code %d from storage engine. + public final static int ER_EVENT_DOES_NOT_EXIST = 1539; //SQLSTATE: HY000 Message: Unknown event '%s' + public final static int ER_EVENT_CANT_ALTER = 1540; //SQLSTATE: HY000 Message: Failed to alter event '%s' + public final static int ER_EVENT_DROP_FAILED = 1541; //SQLSTATE: HY000 Message: Failed to drop %s + public final static int ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG = 1542; //SQLSTATE: HY000 Message: INTERVAL is either not positive or too big + public final static int ER_EVENT_ENDS_BEFORE_STARTS = 1543; //SQLSTATE: HY000 Message: ENDS is either invalid or before STARTS + public final static int ER_EVENT_EXEC_TIME_IN_THE_PAST = 1544; //SQLSTATE: HY000 Message: Event execution time is in the past. Event has been disabled + public final static int ER_EVENT_OPEN_TABLE_FAILED = 1545; //SQLSTATE: HY000 Message: Failed to open mysql.event + public final static int ER_EVENT_NEITHER_M_EXPR_NOR_M_AT = 1546; //SQLSTATE: HY000 Message: No datetime expression provided + public final static int ER_COL_COUNT_DOESNT_MATCH_CORRUPTED = 1547; //SQLSTATE: HY000 Message: Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted + public final static int ER_CANNOT_LOAD_FROM_TABLE = 1548; //SQLSTATE: HY000 Message: Cannot load from mysql.%s. The table is probably corrupted + public final static int ER_EVENT_CANNOT_DELETE = 1549; //SQLSTATE: HY000 Message: Failed to delete the event from mysql.event + public final static int ER_EVENT_COMPILE_ERROR = 1550; //SQLSTATE: HY000 Message: Error during compilation of event's body + public final static int ER_EVENT_SAME_NAME = 1551; //SQLSTATE: HY000 Message: Same old and new event name + public final static int ER_EVENT_DATA_TOO_LONG = 1552; //SQLSTATE: HY000 Message: Data for column '%s' too long + public final static int ER_DROP_INDEX_FK = 1553; //SQLSTATE: HY000 Message: Cannot drop index '%s': needed in a foreign key constraint + public final static int ER_WARN_DEPRECATED_SYNTAX_WITH_VER = 1554; //SQLSTATE: HY000 Message: The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead + public final static int ER_CANT_WRITE_LOCK_LOG_TABLE = 1555; //SQLSTATE: HY000 Message: You can't write-lock a log table. Only read access is possible + public final static int ER_CANT_LOCK_LOG_TABLE = 1556; //SQLSTATE: HY000 Message: You can't use locks with log tables. + public final static int ER_FOREIGN_DUPLICATE_KEY = 1557; //SQLSTATE: 23000 Message: Upholding foreign key constraints for table '%s', entry '%s', key %d would lead to a duplicate entry + public final static int ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE = 1558; //SQLSTATE: HY000 Message: Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysql_upgrade to fix this error. + public final static int ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR = 1559; //SQLSTATE: HY000 Message: Cannot switch out of the row-based binary log format when the session has open temporary tables + public final static int ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT + = 1560; //SQLSTATE: HY000 Message: Cannot change the binary logging format inside a stored function or trigger + public final static int ER_NDB_CANT_SWITCH_BINLOG_FORMAT = 1561; //SQLSTATE: HY000 Message: The NDB cluster engine does not support changing the binlog format on the fly yet + public final static int ER_PARTITION_NO_TEMPORARY = 1562; //SQLSTATE: HY000 Message: Cannot create temporary table with partitions + public final static int ER_PARTITION_CONST_DOMAIN_ERROR = 1563; //SQLSTATE: HY000 Message: Partition constant is out of partition function domain + public final static int ER_PARTITION_FUNCTION_IS_NOT_ALLOWED = 1564; //SQLSTATE: HY000 Message: This partition function is not allowed + public final static int ER_DDL_LOG_ERROR = 1565; //SQLSTATE: HY000 Message: Error in DDL log + public final static int ER_NULL_IN_VALUES_LESS_THAN = 1566; //SQLSTATE: HY000 Message: Not allowed to use NULL value in VALUES LESS THAN + public final static int ER_WRONG_PARTITION_NAME = 1567; //SQLSTATE: HY000 Message: Incorrect partition name + public final static int ER_CANT_CHANGE_TX_ISOLATION = 1568; //SQLSTATE: 25001 Message: Transaction isolation level can't be changed while a transaction is in progress + public final static int ER_DUP_ENTRY_AUTOINCREMENT_CASE = 1569; //SQLSTATE: HY000 Message: ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%s' for key '%s' + public final static int ER_EVENT_MODIFY_QUEUE_ERROR = 1570; //SQLSTATE: HY000 Message: Internal scheduler error %d + public final static int ER_EVENT_SET_VAR_ERROR = 1571; //SQLSTATE: HY000 Message: Error during starting/stopping of the scheduler. Error code %u + public final static int ER_PARTITION_MERGE_ERROR = 1572; //SQLSTATE: HY000 Message: Engine cannot be used in partitioned tables + public final static int ER_CANT_ACTIVATE_LOG = 1573; //SQLSTATE: HY000 Message: Cannot activate '%s' log + public final static int ER_RBR_NOT_AVAILABLE = 1574; //SQLSTATE: HY000 Message: The server was not built with row-based replication + public final static int ER_BASE64_DECODE_ERROR = 1575; //SQLSTATE: HY000 Message: Decoding of base64 string failed + public final static int ER_EVENT_RECURSION_FORBIDDEN = 1576; //SQLSTATE: HY000 Message: Recursion of EVENT DDL statements is forbidden when body is present + public final static int ER_EVENTS_DB_ERROR = 1577; //SQLSTATE: HY000 Message: Cannot proceed because system tables used by Event Scheduler were found damaged at server start + public final static int ER_ONLY_INTEGERS_ALLOWED = 1578; //SQLSTATE: HY000 Message: Only integers allowed as number here + public final static int ER_UNSUPORTED_LOG_ENGINE = 1579; //SQLSTATE: HY000 Message: This storage engine cannot be used for log tables" + public final static int ER_BAD_LOG_STATEMENT = 1580; //SQLSTATE: HY000 Message: You cannot '%s' a log table if logging is enabled + public final static int ER_CANT_RENAME_LOG_TABLE = 1581; //SQLSTATE: HY000 Message: Cannot rename '%s'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to '%s' + public final static int ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT = 1582; //SQLSTATE: 42000 Message: Incorrect parameter count in the call to native function '%s' + public final static int ER_WRONG_PARAMETERS_TO_NATIVE_FCT = 1583; //SQLSTATE: 42000 Message: Incorrect parameters in the call to native function '%s' + public final static int ER_WRONG_PARAMETERS_TO_STORED_FCT = 1584; //SQLSTATE: 42000 Message: Incorrect parameters in the call to stored function '%s' + public final static int ER_NATIVE_FCT_NAME_COLLISION = 1585; //SQLSTATE: HY000 Message: This function '%s' has the same name as a native function + public final static int ER_DUP_ENTRY_WITH_KEY_NAME = 1586; //SQLSTATE: 23000 Message: Duplicate entry '%s' for key '%s' + public final static int ER_BINLOG_PURGE_EMFILE = 1587; //SQLSTATE: HY000 Message: Too many files opened, please execute the command again + public final static int ER_EVENT_CANNOT_CREATE_IN_THE_PAST = 1588; //SQLSTATE: HY000 Message: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. + public final static int ER_EVENT_CANNOT_ALTER_IN_THE_PAST = 1589; //SQLSTATE: HY000 Message: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. + public final static int ER_SLAVE_INCIDENT = 1590; //SQLSTATE: HY000 Message: The incident %s occured on the master. Message: %s + public final static int ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT = 1591; //SQLSTATE: HY000 Message: Table has no partition for some existing values + public final static int ER_BINLOG_UNSAFE_STATEMENT = 1592; //SQLSTATE: HY000 Message: Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. %s + public final static int ER_SLAVE_FATAL_ERROR = 1593; //SQLSTATE: HY000 Message: Fatal error: %s + public final static int ER_SLAVE_RELAY_LOG_READ_FAILURE = 1594; //SQLSTATE: HY000 Message: Relay log read failure: %s + public final static int ER_SLAVE_RELAY_LOG_WRITE_FAILURE = 1595; //SQLSTATE: HY000 Message: Relay log write failure: %s + public final static int ER_SLAVE_CREATE_EVENT_FAILURE = 1596; //SQLSTATE: HY000 Message: Failed to create %s + public final static int ER_SLAVE_MASTER_COM_FAILURE = 1597; //SQLSTATE: HY000 Message: Master command %s failed: %s + public final static int ER_BINLOG_LOGGING_IMPOSSIBLE = 1598; //SQLSTATE: HY000 Message: Binary logging not possible. Message: %s + public final static int ER_VIEW_NO_CREATION_CTX = 1599; //SQLSTATE: HY000 Message: View `%s`.`%s` has no creation context + public final static int ER_VIEW_INVALID_CREATION_CTX = 1600; //SQLSTATE: HY000 Message: Creation context of view `%s`.`%s' is invalid + public final static int ER_SR_INVALID_CREATION_CTX = 1601; //SQLSTATE: HY000 Message: Creation context of stored routine `%s`.`%s` is invalid + public final static int ER_TRG_CORRUPTED_FILE = 1602; //SQLSTATE: HY000 Message: Corrupted TRG file for table `%s`.`%s` + public final static int ER_TRG_NO_CREATION_CTX = 1603; //SQLSTATE: HY000 Message: Triggers for table `%s`.`%s` have no creation context + public final static int ER_TRG_INVALID_CREATION_CTX = 1604; //SQLSTATE: HY000 Message: Trigger creation context of table `%s`.`%s` is invalid + public final static int ER_EVENT_INVALID_CREATION_CTX = 1605; //SQLSTATE: HY000 Message: Creation context of event `%s`.`%s` is invalid + public final static int ER_TRG_CANT_OPEN_TABLE = 1606; //SQLSTATE: HY000 Message: Cannot open table for trigger `%s`.`%s` + public final static int ER_CANT_CREATE_SROUTINE = 1607; //SQLSTATE: HY000 Message: Cannot create stored routine `%s`. Check warnings + public final static int ER_NEVER_USED = 1608; //SQLSTATE: HY000 Message: Ambiguous slave modes combination. %s + public final static int ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT + = 1609; //SQLSTATE: HY000 Message: The BINLOG statement of type `%s` was not preceded by a format description BINLOG statement. + public final static int ER_SLAVE_CORRUPT_EVENT = 1610; //SQLSTATE: HY000 Message: Corrupted replication event was detected + public final static int ER_LOAD_DATA_INVALID_COLUMN = 1611; //SQLSTATE: HY000 Message: Invalid column reference (%s) in LOAD DATA + public final static int ER_LOG_PURGE_NO_FILE = 1612; //SQLSTATE: HY000 Message: Being purged log %s was not found + public final static int ER_XA_RBTIMEOUT = 1613; //SQLSTATE: XA106 Message: XA_RBTIMEOUT: Transaction branch was rolled back: took too long + public final static int ER_XA_RBDEADLOCK = 1614; //SQLSTATE: XA102 Message: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected + public final static int ER_NEED_REPREPARE = 1615; //SQLSTATE: HY000 Message: Prepared statement needs to be re-prepared + public final static int ER_DELAYED_NOT_SUPPORTED = 1616; //SQLSTATE: HY000 Message: DELAYED option not supported for table '%s' + public final static int WARN_NO_MASTER_INFO = 1617; //SQLSTATE: HY000 Message: The master info structure does not exist + public final static int WARN_OPTION_IGNORED = 1618; //SQLSTATE: HY000 Message: <%s> option ignored + public final static int WARN_PLUGIN_DELETE_BUILTIN = 1619; //SQLSTATE: HY000 Message: Built-in plugins cannot be deleted + public final static int WARN_PLUGIN_BUSY = 1620; //SQLSTATE: HY000 Message: Plugin is busy and will be uninstalled on shutdown + public final static int ER_VARIABLE_IS_READONLY = 1621; //SQLSTATE: HY000 Message: %s variable '%s' is read-only. Use SET %s to assign the value + public final static int ER_WARN_ENGINE_TRANSACTION_ROLLBACK = 1622; //SQLSTATE: HY000 Message: Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted + public final static int ER_SLAVE_HEARTBEAT_FAILURE = 1623; //SQLSTATE: HY000 Message: Unexpected master's heartbeat data: %s + public final static int ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE = 1624; //SQLSTATE: HY000 Message: The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%s seconds). + public final static int ER_NDB_REPLICATION_SCHEMA_ERROR = 1625; //SQLSTATE: HY000 Message: Bad schema for mysql.ndb_replication table. Message: %s + public final static int ER_CONFLICT_FN_PARSE_ERROR = 1626; //SQLSTATE: HY000 Message: Error in parsing conflict function. Message: %s + public final static int ER_EXCEPTIONS_WRITE_ERROR = 1627; //SQLSTATE: HY000 Message: Write to exceptions table failed. Message: %s" + public final static int ER_TOO_LONG_TABLE_COMMENT = 1628; //SQLSTATE: HY000 Message: Comment for table '%s' is too long (max = %lu) + public final static int ER_TOO_LONG_FIELD_COMMENT = 1629; //SQLSTATE: HY000 Message: Comment for field '%s' is too long (max = %lu) + public final static int ER_FUNC_INEXISTENT_NAME_COLLISION = 1630; //SQLSTATE: 42000 Message: FUNCTION %s does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual + public final static int ER_DATABASE_NAME = 1631; //SQLSTATE: HY000 Message: Database + public final static int ER_TABLE_NAME = 1632; //SQLSTATE: HY000 Message: Table + public final static int ER_PARTITION_NAME = 1633; //SQLSTATE: HY000 Message: Partition + public final static int ER_SUBPARTITION_NAME = 1634; //SQLSTATE: HY000 Message: Subpartition + public final static int ER_TEMPORARY_NAME = 1635; //SQLSTATE: HY000 Message: Temporary + public final static int ER_RENAMED_NAME = 1636; //SQLSTATE: HY000 Message: Renamed + public final static int ER_TOO_MANY_CONCURRENT_TRXS = 1637; //SQLSTATE: HY000 Message: Too many active concurrent transactions + public final static int WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED = 1638; //SQLSTATE: HY000 Message: Non-ASCII separator arguments are not fully supported + public final static int ER_DEBUG_SYNC_TIMEOUT = 1639; //SQLSTATE: HY000 Message: debug sync point wait timed out + public final static int ER_DEBUG_SYNC_HIT_LIMIT = 1640; //SQLSTATE: HY000 Message: debug sync point hit limit reached + public final static int ER_DUP_SIGNAL_SET = 1641; //SQLSTATE: 42000 Message: Duplicate condition information item '%s' + public final static int ER_SIGNAL_WARN = 1642; //SQLSTATE: 01000 Message: Unhandled user-defined warning condition + public final static int ER_SIGNAL_NOT_FOUND = 1643; //SQLSTATE: 02000 Message: Unhandled user-defined not found condition + public final static int ER_SIGNAL_EXCEPTION = 1644; //SQLSTATE: HY000 Message: Unhandled user-defined exception condition + public final static int ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER = 1645; //SQLSTATE: 0K000 Message: RESIGNAL when handler not active + public final static int ER_SIGNAL_BAD_CONDITION_TYPE = 1646; //SQLSTATE: HY000 Message: SIGNAL/RESIGNAL can only use a CONDITION defined with; //SQLSTATE + public final static int WARN_COND_ITEM_TRUNCATED = 1647; //SQLSTATE: HY000 Message: Data truncated for condition item '%s' + public final static int ER_COND_ITEM_TOO_LONG = 1648; //SQLSTATE: HY000 Message: Data too long for condition item '%s' + public final static int ER_UNKNOWN_LOCALE = 1649; //SQLSTATE: HY000 Message: Unknown locale: '%s' + public final static int ER_SLAVE_IGNORE_SERVER_IDS = 1650; //SQLSTATE: HY000 Message: The requested server id %d clashes with the slave startup option --replicate-same-server-id + public final static int ER_QUERY_CACHE_DISABLED = 1651; //SQLSTATE: HY000 Message: Query cache is disabled; restart the server with query_cache_type=1 to enable it + public final static int ER_SAME_NAME_PARTITION_FIELD = 1652; //SQLSTATE: HY000 Message: Duplicate partition field name '%s' + public final static int ER_PARTITION_COLUMN_LIST_ERROR = 1653; //SQLSTATE: HY000 Message: Inconsistency in usage of column lists for partitioning + public final static int ER_WRONG_TYPE_COLUMN_VALUE_ERROR = 1654; //SQLSTATE: HY000 Message: Partition column values of incorrect type + public final static int ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR = 1655; //SQLSTATE: HY000 Message: Too many fields in '%s' + public final static int ER_MAXVALUE_IN_VALUES_IN = 1656; //SQLSTATE: HY000 Message: Cannot use MAXVALUE as value in VALUES IN + public final static int ER_TOO_MANY_VALUES_ERROR = 1657; //SQLSTATE: HY000 Message: Cannot have more than one value for this type of %s partitioning + public final static int ER_ROW_SINGLE_PARTITION_FIELD_ERROR = 1658; //SQLSTATE: HY000 Message: Row expressions in VALUES IN only allowed for multi-field column partitioning + public final static int ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD + = 1659; //SQLSTATE: HY000 Message: Field '%s' is of a not allowed type for this type of partitioning + public final static int ER_PARTITION_FIELDS_TOO_LONG = 1660; //SQLSTATE: HY000 Message: The total length of the partitioning fields is too large + public final static int ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE = 1661; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since both row-incapable engines and statement-incapable engines are involved. + public final static int ER_BINLOG_ROW_MODE_AND_STMT_ENGINE = 1662; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-based logging. + public final static int ER_BINLOG_UNSAFE_AND_STMT_ENGINE = 1663; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since statement is unsafe, storage engine is limited to statement-based logging, and BINLOG_FORMAT = MIXED. %s + public final static int ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE = 1664; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since statement is in row format and at least one table uses a storage engine limited to statement-based logging. + public final static int ER_BINLOG_STMT_MODE_AND_ROW_ENGINE = 1665; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.%s + public final static int ER_BINLOG_ROW_INJECTION_AND_STMT_MODE = 1666; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT. + public final static int ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE + = 1667; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since more than one engine is involved and at least one engine is self-logging. + public final static int ER_BINLOG_UNSAFE_LIMIT = 1668; //SQLSTATE: HY000 Message: The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. + public final static int ER_BINLOG_UNSAFE_INSERT_DELAYED = 1669; //SQLSTATE: HY000 Message: The statement is unsafe because it uses INSERT DELAYED. This is unsafe because the times when rows are inserted cannot be predicted. + public final static int ER_BINLOG_UNSAFE_SYSTEM_TABLE = 1670; //SQLSTATE: HY000 Message: The statement is unsafe because it uses the general log, slow query log, or performance_schema table(s). This is unsafe because system tables may differ on slaves. + public final static int ER_BINLOG_UNSAFE_AUTOINC_COLUMNS = 1671; //SQLSTATE: HY000 Message: Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly. + public final static int ER_BINLOG_UNSAFE_UDF = 1672; //SQLSTATE: HY000 Message: Statement is unsafe because it uses a UDF which may not return the same value on the slave. + public final static int ER_BINLOG_UNSAFE_SYSTEM_VARIABLE = 1673; //SQLSTATE: HY000 Message: Statement is unsafe because it uses a system variable that may have a different value on the slave. + public final static int ER_BINLOG_UNSAFE_SYSTEM_FUNCTION = 1674; //SQLSTATE: HY000 Message: Statement is unsafe because it uses a system function that may return a different value on the slave. + public final static int ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS = 1675; //SQLSTATE: HY000 Message: Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction. + public final static int ER_MESSAGE_AND_STATEMENT = 1676; //SQLSTATE: HY000 Message: %s Statement: %s + public final static int ER_SLAVE_CONVERSION_FAILED = 1677; //SQLSTATE: HY000 Message: Column %d of table '%s.%s' cannot be converted from type '%s' to type '%s' + public final static int ER_SLAVE_CANT_CREATE_CONVERSION = 1678; //SQLSTATE: HY000 Message: Can't create conversion table for table '%s.%s' + public final static int ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT + = 1679; //SQLSTATE: HY000 Message: Cannot modify @@session.binlog_format inside a transaction + public final static int ER_PATH_LENGTH = 1680; //SQLSTATE: HY000 Message: The path specified for %s is too long. + public final static int ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT = 1681; //SQLSTATE: HY000 Message: The syntax '%s' is deprecated and will be removed in MySQL %s. + public final static int ER_WRONG_NATIVE_TABLE_STRUCTURE = 1682; //SQLSTATE: HY000 Message: Native table '%s'.'%s' has the wrong structure + public final static int ER_WRONG_PERFSCHEMA_USAGE = 1683; //SQLSTATE: HY000 Message: Invalid performance_schema usage. + public final static int ER_WARN_I_S_SKIPPED_TABLE = 1684; //SQLSTATE: HY000 Message: Table '%s'.'%s' was skipped since its definition is being modified by concurrent DDL statement + public final static int ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + = 1685; //SQLSTATE: HY000 Message: Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction + public final static int ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT + = 1686; //SQLSTATE: HY000 Message: Cannot change the binlog direct flag inside a stored function or trigger + public final static int ER_SPATIAL_MUST_HAVE_GEOM_COL = 1687; //SQLSTATE: 42000 Message: A SPATIAL index may only contain a geometrical type column + public final static int ER_TOO_LONG_INDEX_COMMENT = 1688; //SQLSTATE: HY000 Message: Comment for index '%s' is too long (max = %lu) + public final static int ER_LOCK_ABORTED = 1689; //SQLSTATE: HY000 Message: Wait on a lock was aborted due to a pending exclusive lock + public final static int ER_DATA_OUT_OF_RANGE = 1690; //SQLSTATE: 22003 Message: %s value is out of range in '%s' + public final static int ER_WRONG_SPVAR_TYPE_IN_LIMIT = 1691; //SQLSTATE: HY000 Message: A variable of a non-integer type in LIMIT clause + public final static int ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE + = 1692; //SQLSTATE: HY000 Message: Mixing self-logging and non-self-logging engines in a statement is unsafe. + public final static int ER_BINLOG_UNSAFE_MIXED_STATEMENT = 1693; //SQLSTATE: HY000 Message: Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them. + public final static int ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN + = 1694; //SQLSTATE: HY000 Message: Cannot modify @@session.sql_log_bin inside a transaction + public final static int ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN + = 1695; //SQLSTATE: HY000 Message: Cannot change the sql_log_bin inside a stored function or trigger + public final static int ER_FAILED_READ_FROM_PAR_FILE = 1696; //SQLSTATE: HY000 Message: Failed to read from the .par file + public final static int ER_VALUES_IS_NOT_INT_TYPE_ERROR = 1697; //SQLSTATE: HY000 Message: VALUES value for partition '%s' must have type INT + public final static int ER_ACCESS_DENIED_NO_PASSWORD_ERROR = 1698; //SQLSTATE: 28000 Message: Access denied for user '%s'@'%s' + public final static int ER_SET_PASSWORD_AUTH_PLUGIN = 1699; //SQLSTATE: HY000 Message: SET PASSWORD has no significance for users authenticating via plugins + public final static int ER_GRANT_PLUGIN_USER_EXISTS = 1700; //SQLSTATE: HY000 Message: GRANT with IDENTIFIED WITH is illegal because the user %-.*s already exists + public final static int ER_TRUNCATE_ILLEGAL_FK = 1701; //SQLSTATE: 42000 Message: Cannot truncate a table referenced in a foreign key constraint (%s) + public final static int ER_PLUGIN_IS_PERMANENT = 1702; //SQLSTATE: HY000 Message: Plugin '%s' is force_plus_permanent and can not be unloaded + public final static int ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN = 1703; //SQLSTATE: HY000 Message: The requested value for the heartbeat period is less than 1 millisecond. The value is reset to 0, meaning that heartbeating will effectively be disabled. + public final static int ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX = 1704; //SQLSTATE: HY000 Message: The requested value for the heartbeat period exceeds the value of `slave_net_timeout' seconds. A sensible value for the period should be less than the timeout. + public final static int ER_STMT_CACHE_FULL = 1705; //SQLSTATE: HY000 Message: Multi-row statements required more than 'max_binlog_stmt_cache_size' bytes of storage; increase this mysqld variable and try again - public final static int ER_ACCESS_DENIED_ERROR = 1045; + public final static int ER_MULTI_UPDATE_KEY_CONFLICT = 1706; //SQLSTATE: HY000 Message: Primary key/partition key update is not allowed since the table is updated both as '%s' and '%s'. + public final static int ER_TABLE_NEEDS_REBUILD = 1707; //SQLSTATE: HY000 Message: Table rebuild required. Please do "ALTER TABLE `%s` FORCE" or dump/reload to fix it! + public final static int WARN_OPTION_BELOW_LIMIT = 1708; //SQLSTATE: HY000 Message: The value of '%s' should be no less than the value of '%s' + public final static int ER_INDEX_COLUMN_TOO_LONG = 1709; //SQLSTATE: HY000 Message: Index column size too large. The maximum column size is %lu bytes. + public final static int ER_ERROR_IN_TRIGGER_BODY = 1710; //SQLSTATE: HY000 Message: Trigger '%s' has an error in its body: '%s' + public final static int ER_ERROR_IN_UNKNOWN_TRIGGER_BODY = 1711; //SQLSTATE: HY000 Message: Unknown trigger has an error in its body: '%s' + public final static int ER_INDEX_CORRUPT = 1712; //SQLSTATE: HY000 Message: Index %s is corrupted + public final static int ER_UNDO_RECORD_TOO_BIG = 1713; //SQLSTATE: HY000 Message: Undo log record is too big. + public final static int ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT = 1714; //SQLSTATE: HY000 Message: INSERT IGNORE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE = 1715; //SQLSTATE: HY000 Message: INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_REPLACE_SELECT = 1716; //SQLSTATE: HY000 Message: REPLACE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT = 1717; //SQLSTATE: HY000 Message: CREATE... IGNORE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT = 1718; //SQLSTATE: HY000 Message: CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_UPDATE_IGNORE = 1719; //SQLSTATE: HY000 Message: UPDATE IGNORE is unsafe because the order in which rows are updated determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave. + public final static int ER_PLUGIN_NO_UNINSTALL = 1720; //SQLSTATE: HY000 Message: Plugin '%s' is marked as not dynamically uninstallable. You have to stop the server to uninstall it. + public final static int ER_PLUGIN_NO_INSTALL = 1721; //SQLSTATE: HY000 Message: Plugin '%s' is marked as not dynamically installable. You have to stop the server to install it. + public final static int ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT = 1722; //SQLSTATE: HY000 Message: Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC = 1723; //SQLSTATE: HY000 Message: CREATE TABLE... SELECT... on a table with an auto-increment column is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are inserted. This order cannot be predicted and may differ on master and the slave. + public final static int ER_BINLOG_UNSAFE_INSERT_TWO_KEYS = 1724; //SQLSTATE: HY000 Message: INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe + public final static int ER_TABLE_IN_FK_CHECK = 1725; //SQLSTATE: HY000 Message: Table is being used in foreign key check. + public final static int ER_UNSUPPORTED_ENGINE = 1726; //SQLSTATE: HY000 Message: Storage engine '%s' does not support system tables. [%s.%s] + public final static int ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST = 1727; //SQLSTATE: HY000 Message: INSERT into autoincrement field which is not the first part in the composed primary key is unsafe. + public final static int ER_CANNOT_LOAD_FROM_TABLE_V2 = 1728; //SQLSTATE: HY000 Message: Cannot load from %s.%s. The table is probably corrupted + public final static int ER_MASTER_DELAY_VALUE_OUT_OF_RANGE = 1729; //SQLSTATE: HY000 Message: The requested value %u for the master delay exceeds the maximum %u + public final static int ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT + = 1730; //SQLSTATE: HY000 Message: Only Format_description_log_event and row events are allowed in BINLOG statements (but %s was provided) + public final static int ER_PARTITION_EXCHANGE_DIFFERENT_OPTION = 1731; //SQLSTATE: HY000 Message: Non matching attribute '%s' between partition and table + public final static int ER_PARTITION_EXCHANGE_PART_TABLE = 1732; //SQLSTATE: HY000 Message: Table to exchange with partition is partitioned: '%s' + public final static int ER_PARTITION_EXCHANGE_TEMP_TABLE = 1733; //SQLSTATE: HY000 Message: Table to exchange with partition is temporary: '%s' + public final static int ER_PARTITION_INSTEAD_OF_SUBPARTITION = 1734; //SQLSTATE: HY000 Message: Subpartitioned table, use subpartition instead of partition + public final static int ER_UNKNOWN_PARTITION = 1735; //SQLSTATE: HY000 Message: Unknown partition '%s' in table '%s' + public final static int ER_TABLES_DIFFERENT_METADATA = 1736; //SQLSTATE: HY000 Message: Tables have different definitions + public final static int ER_ROW_DOES_NOT_MATCH_PARTITION = 1737; //SQLSTATE: HY000 Message: Found a row that does not match the partition + public final static int ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX = 1738; //SQLSTATE: HY000 Message: Option binlog_cache_size (%lu) is greater than max_binlog_cache_size (%lu); setting binlog_cache_size equal to max_binlog_cache_size. + public final static int ER_WARN_INDEX_NOT_APPLICABLE = 1739; //SQLSTATE: HY000 Message: Cannot use %s access on index '%s' due to type or collation conversion on field '%s' + public final static int ER_PARTITION_EXCHANGE_FOREIGN_KEY = 1740; //SQLSTATE: HY000 Message: Table to exchange with partition has foreign key references: '%s' + public final static int ER_NO_SUCH_KEY_VALUE = 1741; //SQLSTATE: HY000 Message: Key value '%s' was not found in table '%s.%s' + public final static int ER_RPL_INFO_DATA_TOO_LONG = 1742; //SQLSTATE: HY000 Message: Data for column '%s' too long + public final static int ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE = 1743; //SQLSTATE: HY000 Message: Replication event checksum verification failed while reading from network. + public final static int ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE = 1744; //SQLSTATE: HY000 Message: Replication event checksum verification failed while reading from a log file. + public final static int ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX = 1745; //SQLSTATE: HY000 Message: Option binlog_stmt_cache_size (%lu) is greater than max_binlog_stmt_cache_size (%lu); setting binlog_stmt_cache_size equal to max_binlog_stmt_cache_size. + public final static int ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT = 1746; //SQLSTATE: HY000 Message: Can't update table '%s' while '%s' is being created. + public final static int ER_PARTITION_CLAUSE_ON_NONPARTITIONED = 1747; //SQLSTATE: HY000 Message: PARTITION () clause on non partitioned table + public final static int ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET = 1748; //SQLSTATE: HY000 Message: Found a row not matching the given partition set + public final static int ER_NO_SUCH_PARTITION__UNUSED = 1749; //SQLSTATE: HY000 Message: partition '%s' doesn't exist + public final static int ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE = 1750; //SQLSTATE: HY000 Message: Failure while changing the type of replication repository: %s. + public final static int ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE + = 1751; //SQLSTATE: HY000 Message: The creation of some temporary tables could not be rolled back. + public final static int ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE + = 1752; //SQLSTATE: HY000 Message: Some temporary tables were dropped, but these operations could not be rolled back. + public final static int ER_MTS_FEATURE_IS_NOT_SUPPORTED = 1753; //SQLSTATE: HY000 Message: %s is not supported in multi-threaded slave mode. %s + public final static int ER_MTS_UPDATED_DBS_GREATER_MAX = 1754; //SQLSTATE: HY000 Message: The number of modified databases exceeds the maximum %d; the database names will not be included in the replication event metadata. + public final static int ER_MTS_CANT_PARALLEL = 1755; //SQLSTATE: HY000 Message: Cannot execute the current event group in the parallel mode. Encountered event %s, relay-log name %s, position %s which prevents execution of this event group in parallel mode. Reason: %s. + public final static int ER_MTS_INCONSISTENT_DATA = 1756; //SQLSTATE: HY000 Message: %s + public final static int ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING = 1757; //SQLSTATE: HY000 Message: FULLTEXT index is not supported for partitioned tables. + public final static int ER_DA_INVALID_CONDITION_NUMBER = 1758; //SQLSTATE: 35000 Message: Invalid condition number + public final static int ER_INSECURE_PLAIN_TEXT = 1759; //SQLSTATE: HY000 Message: Sending passwords in plain text without SSL/TLS is extremely insecure. + public final static int ER_INSECURE_CHANGE_MASTER = 1760; //SQLSTATE: HY000 Message: Storing MySQL user name or password information in the master.info repository is not secure and is therefore not recommended. Please see the MySQL Manual for more about this issue and possible alternatives. + public final static int ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO = 1761; //SQLSTATE: 23000 Message: Foreign key constraint for table '%s', record '%s' would lead to a duplicate entry in table '%s', key '%s' + public final static int ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO = 1762; //SQLSTATE: 23000 Message: Foreign key constraint for table '%s', record '%s' would lead to a duplicate entry in a child table + public final static int ER_SQLTHREAD_WITH_SECURE_SLAVE = 1763; //SQLSTATE: HY000 Message: Setting authentication options is not possible when only the Slave SQL Thread is being started. + public final static int ER_TABLE_HAS_NO_FT = 1764; //SQLSTATE: HY000 Message: The table does not have FULLTEXT index to support this query + public final static int ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER = 1765; //SQLSTATE: HY000 Message: The system variable %s cannot be set in stored functions or triggers. + public final static int ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION = 1766; //SQLSTATE: HY000 Message: The system variable %s cannot be set when there is an ongoing transaction. + public final static int ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST = 1767; //SQLSTATE: HY000 Message: The system variable @@SESSION.GTID_NEXT has the value %s, which is not listed in @@SESSION.GTID_NEXT_LIST. + public final static int ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION_WHEN_GTID_NEXT_LIST_IS_NULL + = 1768; //SQLSTATE: HY000 Message: When @@SESSION.GTID_NEXT_LIST == NULL, the system variable @@SESSION.GTID_NEXT cannot change inside a transaction. + public final static int ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION = 1769; //SQLSTATE: HY000 Message: The statement 'SET %s' cannot invoke a stored function. + public final static int ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL + = 1770; //SQLSTATE: HY000 Message: The system variable @@SESSION.GTID_NEXT cannot be 'AUTOMATIC' when @@SESSION.GTID_NEXT_LIST is non-NULL. + public final static int ER_SKIPPING_LOGGED_TRANSACTION = 1771; //SQLSTATE: HY000 Message: Skipping transaction %s because it has already been executed and logged. + public final static int ER_MALFORMED_GTID_SET_SPECIFICATION = 1772; //SQLSTATE: HY000 Message: Malformed GTID set specification '%s'. + public final static int ER_MALFORMED_GTID_SET_ENCODING = 1773; //SQLSTATE: HY000 Message: Malformed GTID set encoding. + public final static int ER_MALFORMED_GTID_SPECIFICATION = 1774; //SQLSTATE: HY000 Message: Malformed GTID specification '%s'. + public final static int ER_GNO_EXHAUSTED = 1775; //SQLSTATE: HY000 Message: Impossible to generate Global Transaction Identifier: the integer component reached the maximal value. Restart the server with a new server_uuid. + public final static int ER_BAD_SLAVE_AUTO_POSITION = 1776; //SQLSTATE: HY000 Message: Parameters MASTER_LOG_FILE, MASTER_LOG_POS, RELAY_LOG_FILE and RELAY_LOG_POS cannot be set when MASTER_AUTO_POSITION is active. + public final static int ER_AUTO_POSITION_REQUIRES_GTID_MODE_ON = 1777; //SQLSTATE: HY000 Message: CHANGE MASTER TO MASTER_AUTO_POSITION = 1 can only be executed when GTID_MODE = ON. + public final static int ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET + = 1778; //SQLSTATE: HY000 Message: Cannot execute statements with implicit commit inside a transaction when GTID_NEXT != AUTOMATIC or GTID_NEXT_LIST != NULL. + public final static int ER_GTID_MODE_2_OR_3_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON + = 1779; //SQLSTATE: HY000 Message: GTID_MODE = ON or GTID_MODE = UPGRADE_STEP_2 requires ENFORCE_GTID_CONSISTENCY = 1. + public final static int ER_GTID_MODE_REQUIRES_BINLOG = 1780; //SQLSTATE: HY000 Message: GTID_MODE = ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates. + public final static int ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF + = 1781; //SQLSTATE: HY000 Message: GTID_NEXT cannot be set to UUID:NUMBER when GTID_MODE = OFF. + public final static int ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON + = 1782; //SQLSTATE: HY000 Message: GTID_NEXT cannot be set to ANONYMOUS when GTID_MODE = ON. + public final static int ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF + = 1783; //SQLSTATE: HY000 Message: GTID_NEXT_LIST cannot be set to a non-NULL value when GTID_MODE = OFF. + public final static int ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF = 1784; //SQLSTATE: HY000 Message: Found a Gtid_log_event or Previous_gtids_log_event when GTID_MODE = OFF. + public final static int ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE = 1785; //SQLSTATE: HY000 Message: When ENFORCE_GTID_CONSISTENCY = 1, updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables. + public final static int ER_GTID_UNSAFE_CREATE_SELECT = 1786; //SQLSTATE: HY000 Message: CREATE TABLE ... SELECT is forbidden when ENFORCE_GTID_CONSISTENCY = 1. + public final static int ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION + = 1787; //SQLSTATE: HY000 Message: When ENFORCE_GTID_CONSISTENCY = 1, the statements CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE can be executed in a non-transactional context only, and require that AUTOCOMMIT = 1. + public final static int ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME + = 1788; //SQLSTATE: HY000 Message: The value of GTID_MODE can only change one step at a time: OFF <-> UPGRADE_STEP_1 <-> UPGRADE_STEP_2 <-> ON. Also note that this value must be stepped up or down simultaneously on all servers; see the Manual for instructions. + public final static int ER_MASTER_HAS_PURGED_REQUIRED_GTIDS = 1789; //SQLSTATE: HY000 Message: The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires. + public final static int ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID = 1790; //SQLSTATE: HY000 Message: GTID_NEXT cannot be changed by a client that owns a GTID. The client owns %s. Ownership is released on COMMIT or ROLLBACK. + public final static int ER_UNKNOWN_EXPLAIN_FORMAT = 1791; //SQLSTATE: HY000 Message: Unknown EXPLAIN format name: '%s' + public final static int ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION = 1792; //SQLSTATE: 25006 Message: Cannot execute statement in a READ ONLY transaction. + public final static int ER_TOO_LONG_TABLE_PARTITION_COMMENT = 1793; //SQLSTATE: HY000 Message: Comment for table partition '%s' is too long (max = %lu) + public final static int ER_SLAVE_CONFIGURATION = 1794; //SQLSTATE: HY000 Message: Slave is not configured or failed to initialize properly. You must at least set --server-id to enable either a master or a slave. Additional error messages can be found in the MySQL error log. + public final static int ER_INNODB_FT_LIMIT = 1795; //SQLSTATE: HY000 Message: InnoDB presently supports one FULLTEXT index creation at a time + public final static int ER_INNODB_NO_FT_TEMP_TABLE = 1796; //SQLSTATE: HY000 Message: Cannot create FULLTEXT index on temporary InnoDB table + public final static int ER_INNODB_FT_WRONG_DOCID_COLUMN = 1797; //SQLSTATE: HY000 Message: Column '%s' is of wrong type for an InnoDB FULLTEXT index + public final static int ER_INNODB_FT_WRONG_DOCID_INDEX = 1798; //SQLSTATE: HY000 Message: Index '%s' is of wrong type for an InnoDB FULLTEXT index + public final static int ER_INNODB_ONLINE_LOG_TOO_BIG = 1799; //SQLSTATE: HY000 Message: Creating index '%s' required more than 'innodb_online_alter_log_max_size' bytes of modification log. Please try again. + public final static int ER_UNKNOWN_ALTER_ALGORITHM = 1800; //SQLSTATE: HY000 Message: Unknown ALGORITHM '%s' + public final static int ER_UNKNOWN_ALTER_LOCK = 1801; //SQLSTATE: HY000 Message: Unknown LOCK type '%s' + public final static int ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS = 1802; //SQLSTATE: HY000 Message: CHANGE MASTER cannot be executed when the slave was stopped with an error or killed in MTS mode. Consider using RESET SLAVE or START SLAVE UNTIL. + public final static int ER_MTS_RECOVERY_FAILURE = 1803; //SQLSTATE: HY000 Message: Cannot recover after SLAVE errored out in parallel execution mode. Additional error messages can be found in the MySQL error log. + public final static int ER_MTS_RESET_WORKERS = 1804; //SQLSTATE: HY000 Message: Cannot clean up worker info tables. Additional error messages can be found in the MySQL error log. + public final static int ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 = 1805; //SQLSTATE: HY000 Message: Column count of %s.%s is wrong. Expected %d, found %d. The table is probably corrupted + public final static int ER_SLAVE_SILENT_RETRY_TRANSACTION = 1806; //SQLSTATE: HY000 Message: Slave must silently retry current transaction + public final static int ER_DISCARD_FK_CHECKS_RUNNING = 1807; //SQLSTATE: HY000 Message: There is a foreign key check running on table '%s'. Cannot discard the table. + public final static int ER_TABLE_SCHEMA_MISMATCH = 1808; //SQLSTATE: HY000 Message: Schema mismatch (%s) + public final static int ER_TABLE_IN_SYSTEM_TABLESPACE = 1809; //SQLSTATE: HY000 Message: Table '%s' in system tablespace + public final static int ER_IO_READ_ERROR = 1810; //SQLSTATE: HY000 Message: IO Read error: (%lu, %s) %s + public final static int ER_IO_WRITE_ERROR = 1811; //SQLSTATE: HY000 Message: IO Write error: (%lu, %s) %s + public final static int ER_TABLESPACE_MISSING = 1812; //SQLSTATE: HY000 Message: Tablespace is missing for table '%s' + public final static int ER_TABLESPACE_EXISTS = 1813; //SQLSTATE: HY000 Message: Tablespace for table '%s' exists. Please DISCARD the tablespace before IMPORT. + public final static int ER_TABLESPACE_DISCARDED = 1814; //SQLSTATE: HY000 Message: Tablespace has been discarded for table '%s' + public final static int ER_INTERNAL_ERROR = 1815; //SQLSTATE: HY000 Message: Internal error: %s + public final static int ER_INNODB_IMPORT_ERROR = 1816; //SQLSTATE: HY000 Message: ALTER TABLE '%s' IMPORT TABLESPACE failed with error %lu : '%s' + public final static int ER_INNODB_INDEX_CORRUPT = 1817; //SQLSTATE: HY000 Message: Index corrupt: %s + public final static int ER_INVALID_YEAR_COLUMN_LENGTH = 1818; //SQLSTATE: HY000 Message: YEAR(%lu) column type is deprecated. Creating YEAR(4) column instead. + public final static int ER_NOT_VALID_PASSWORD = 1819; //SQLSTATE: HY000 Message: Your password does not satisfy the current policy requirements + public final static int ER_MUST_CHANGE_PASSWORD = 1820; //SQLSTATE: HY000 Message: You must SET PASSWORD before executing this statement + public final static int ER_FK_NO_INDEX_CHILD = 1821; //SQLSTATE: HY000 Message: Failed to add the foreign key constaint. Missing index for constraint '%s' in the foreign table '%s' + public final static int ER_FK_NO_INDEX_PARENT = 1822; //SQLSTATE: HY000 Message: Failed to add the foreign key constaint. Missing index for constraint '%s' in the referenced table '%s' + public final static int ER_FK_FAIL_ADD_SYSTEM = 1823; //SQLSTATE: HY000 Message: Failed to add the foreign key constraint '%s' to system tables + public final static int ER_FK_CANNOT_OPEN_PARENT = 1824; //SQLSTATE: HY000 Message: Failed to open the referenced table '%s' + public final static int ER_FK_INCORRECT_OPTION = 1825; //SQLSTATE: HY000 Message: Failed to add the foreign key constraint on table '%s'. Incorrect options in FOREIGN KEY constraint '%s' + public final static int ER_FK_DUP_NAME = 1826; //SQLSTATE: HY000 Message: Duplicate foreign key constraint name '%s' + public final static int ER_PASSWORD_FORMAT = 1827; //SQLSTATE: HY000 Message: The password hash doesn't have the expected format. Check if the correct password algorithm is being used with the PASSWORD() function. + public final static int ER_FK_COLUMN_CANNOT_DROP = 1828; //SQLSTATE: HY000 Message: Cannot drop column '%s': needed in a foreign key constraint '%s' + public final static int ER_FK_COLUMN_CANNOT_DROP_CHILD = 1829; //SQLSTATE: HY000 Message: Cannot drop column '%s': needed in a foreign key constraint '%s' of table '%s' + public final static int ER_FK_COLUMN_NOT_NULL = 1830; //SQLSTATE: HY000 Message: Column '%s' cannot be NOT NULL: needed in a foreign key constraint '%s' SET NULL + public final static int ER_DUP_INDEX = 1831; //SQLSTATE: HY000 Message: Duplicate index '%s' defined on the table '%s.%s'. This is deprecated and will be disallowed in a future release. + public final static int ER_FK_COLUMN_CANNOT_CHANGE = 1832; //SQLSTATE: HY000 Message: Cannot change column '%s': used in a foreign key constraint '%s' + public final static int ER_FK_COLUMN_CANNOT_CHANGE_CHILD = 1833; //SQLSTATE: HY000 Message: Cannot change column '%s': used in a foreign key constraint '%s' of table '%s' + public final static int ER_FK_CANNOT_DELETE_PARENT = 1834; //SQLSTATE: HY000 Message: Cannot delete rows from table which is parent in a foreign key constraint '%s' of table '%s' + public final static int ER_MALFORMED_PACKET = 1835; //SQLSTATE: HY000 Message: Malformed communication packet. + public final static int ER_READ_ONLY_MODE = 1836; //SQLSTATE: HY000 Message: Running in read-only mode + public final static int ER_GTID_NEXT_TYPE_UNDEFINED_GROUP = 1837; //SQLSTATE: HY000 Message: When GTID_NEXT is set to a GTID, you must explicitly set it again after a COMMIT or ROLLBACK. If you see this error message in the slave SQL thread, it means that a table in the current transaction is transactional on the master and non-transactional on the slave. In a client connection, it means that you executed SET GTID_NEXT before a transaction and forgot to set GTID_NEXT to a different identifier or to 'AUTOMATIC' after COMMIT or ROLLBACK. Current GTID_NEXT is '%s'. + public final static int ER_VARIABLE_NOT_SETTABLE_IN_SP = 1838; //SQLSTATE: HY000 Message: The system variable %s cannot be set in stored procedures. + public final static int ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF + = 1839; //SQLSTATE: HY000 Message: GTID_PURGED can only be set when GTID_MODE = ON. + public final static int ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY + = 1840; //SQLSTATE: HY000 Message: GTID_PURGED can only be set when GTID_EXECUTED is empty. + public final static int ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY + = 1841; //SQLSTATE: HY000 Message: GTID_PURGED can only be set when there are no ongoing transactions (not even in other clients). + public final static int ER_GTID_PURGED_WAS_CHANGED = 1842; //SQLSTATE: HY000 Message: GTID_PURGED was changed from '%s' to '%s'. + public final static int ER_GTID_EXECUTED_WAS_CHANGED = 1843; //SQLSTATE: HY000 Message: GTID_EXECUTED was changed from '%s' to '%s'. + public final static int ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES = 1844; //SQLSTATE: HY000 Message: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT, and both replicated and non replicated tables are written to. + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED = 1845; //SQLSTATE: 0A000 Message: %s is not supported for this operation. Try %s. + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON = 1846; //SQLSTATE: 0A000 Message: %s is not supported. Reason: %s. Try %s. + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY + = 1847; //SQLSTATE: HY000 Message: COPY algorithm requires a lock + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION + = 1848; //SQLSTATE: HY000 Message: Partition specific operations do not yet support LOCK/ALGORITHM + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME + = 1849; //SQLSTATE: HY000 Message: Columns participating in a foreign key are renamed + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE + = 1850; //SQLSTATE: HY000 Message: Cannot change column type INPLACE + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK + = 1851; //SQLSTATE: HY000 Message: Adding foreign keys needs foreign_key_checks=OFF + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_IGNORE + = 1852; //SQLSTATE: HY000 Message: Creating unique indexes with IGNORE requires COPY algorithm to remove duplicate rows + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK + = 1853; //SQLSTATE: HY000 Message: Dropping a primary key is not allowed without also adding a new primary key + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC + = 1854; //SQLSTATE: HY000 Message: Adding an auto-increment column requires a lock + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS + = 1855; //SQLSTATE: HY000 Message: Cannot replace hidden FTS_DOC_ID with a user-visible one + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS + = 1856; //SQLSTATE: HY000 Message: Cannot drop or rename FTS_DOC_ID + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS = 1857; //SQLSTATE: HY000 Message: Fulltext index creation requires a lock + public final static int ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE + = 1858; //SQLSTATE: HY000 Message: sql_slave_skip_counter can not be set when the server is running with GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction + public final static int ER_DUP_UNKNOWN_IN_INDEX = 1859; //SQLSTATE: 23000 Message: Duplicate entry for key '%s' + public final static int ER_IDENT_CAUSES_TOO_LONG_PATH = 1860; //SQLSTATE: HY000 Message: Long database name and identifier for object resulted in path length exceeding %d characters. Path: '%s'. + public final static int ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL + = 1861; //SQLSTATE: HY000 Message: cannot silently convert NULL values, as required in this SQL_MODE; was introduced in 5.7.1. + public final static int ER_MUST_CHANGE_PASSWORD_LOGIN = 1862; //SQLSTATE: HY000 Message: Your password has expired. To log in you must change it using a client that supports expired passwords. was introduced in 5.7.1. + public final static int ER_ROW_IN_WRONG_PARTITION = 1863; //SQLSTATE: HY000 Message: Found a row in wrong partition %s; was introduced in 5.7.1. + public final static int ER_MTS_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX = 1864; //SQLSTATE: HY000 Message: Cannot schedule event %s, relay-log name %s, position %s to Worker thread because its size %lu exceeds %lu of slave_pending_jobs_size_max.; was introduced in 5.7.2. - public final static int ER_ALTER_INFO = 1088; + public final static int ER_INNODB_NO_FT_USES_PARSER = 1865; //SQLSTATE: HY000 Message: Cannot CREATE FULLTEXT INDEX WITH PARSER on InnoDB table; was introduced in 5.7.2. + public final static int ER_BINLOG_LOGICAL_CORRUPTION = 1866; //SQLSTATE: HY000 Message: The binary log file '%s' is logically corrupted: %s; was introduced in 5.7.2. + public final static int ER_WARN_PURGE_LOG_IN_USE = 1867; //SQLSTATE: HY000 Message: file %s was not purged because it was being read by %d thread(s), purged only %d out of %d files. was introduced in 5.7.2. + public final static int ER_WARN_PURGE_LOG_IS_ACTIVE = 1868; //SQLSTATE: HY000 Message: file %s was not purged because it is the active log file.; was introduced in 5.7.2. + public final static int ER_AUTO_INCREMENT_CONFLICT = 1869; //SQLSTATE: HY000 Message: Auto-increment value in UPDATE conflicts with internally generated values; was introduced in 5.7.2. + public final static int WARN_ON_BLOCKHOLE_IN_RBR = 1870; //SQLSTATE: HY000 Message: Row events are not logged for %s statements that modify BLACKHOLE tables in row format. Table(s): '%s'; was introduced in 5.7.2. + public final static int ER_SLAVE_MI_INIT_REPOSITORY = 1871; //SQLSTATE: HY000 Message: Slave failed to initialize master info structure from the repository; was introduced in 5.7.2. + public final static int ER_SLAVE_RLI_INIT_REPOSITORY = 1872; //SQLSTATE: HY000 Message: Slave failed to initialize relay log info structure from the repository; was introduced in 5.7.2. + public final static int ER_ACCESS_DENIED_CHANGE_USER_ERROR = 1873; //SQLSTATE: 28000 Message: Access denied trying to change to user '%s'@'%s' (using password: %s). Disconnecting. was introduced in 5.7.2. + public final static int ER_INNODB_READ_ONLY = 1874; //SQLSTATE: HY000 Message: InnoDB is in read only mode.; was introduced in 5.7.2. + public final static int ER_STOP_SLAVE_SQL_THREAD_TIMEOUT = 1875; //SQLSTATE: HY000 Message: STOP SLAVE command execution is incomplete: Slave SQL thread got the stop signal, thread is busy, SQL thread will stop once the current task is complete.; was introduced in 5.7.2. + public final static int ER_STOP_SLAVE_IO_THREAD_TIMEOUT = 1876; //SQLSTATE: HY000 Message: STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete.; was introduced in 5.7.2. + public final static int ER_TABLE_CORRUPT = 1877; //SQLSTATE: HY000 Message: Operation cannot be performed. The table '%s.%s' is missing, corrupt or contains bad data.; was introduced in 5.7.2. + public final static int ER_TEMP_FILE_WRITE_FAILURE = 1878; //SQLSTATE: HY000 Message: Temporary file write failure.; was introduced in 5.7.3. + public final static int ER_INNODB_FT_AUX_NOT_HEX_ID = 1879; //SQLSTATE: HY000 Message: Upgrade index name failed, please use create index(alter table) algorithm copy to rebuild index.; was introduced in 5.7.4. + public final static int ER_OLD_TEMPORALS_UPGRADED = 1880; //SQLSTATE: HY000 Message: TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format.; was introduced in 5.7.4. + public final static int ER_INNODB_FORCED_RECOVERY = 1881; //SQLSTATE: HY000 Message: Operation not allowed when innodb_forced_recovery > 0.; was introduced in 5.7.4. + public final static int ER_AES_INVALID_IV = 1882; //SQLSTATE: HY000 Message: The initialization vector supplied to %s is too short. Must be at least %d bytes long; was introduced in 5.7.4. + public final static int ER_FILE_CORRUPT = 1883; //SQLSTATE: HY000 Message: File %s is corrupted + public final static int ER_ERROR_ON_MASTER = 1884; //SQLSTATE: HY000 Message: Query partially completed on the master (error on master: %d) and was aborted. There is a chance that your master is inconsistent at this point. If you are sure that your master is ok, run this query manually on the slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;. Query:'%s' + public final static int ER_INCONSISTENT_ERROR = 1885; //SQLSTATE: HY000 Message: Query caused different errors on master and slave. Error on master: message (format)='%s' error code=%d; Error on slave:actual message='%s', error code=%d. Default database:'%s'. Query:'%s' + public final static int ER_STORAGE_ENGINE_NOT_LOADED = 1886; //SQLSTATE: HY000 Message: Storage engine for table '%s'.'%s' is not loaded. + public final static int ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER = 1887; //SQLSTATE: 0Z002 Message: GET STACKED DIAGNOSTICS when handler not active + public final static int ER_WARN_LEGACY_SYNTAX_CONVERTED = 1888; //SQLSTATE: HY000 Message: %s is no longer supported. The statement was converted to %s. + public final static int ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN = 1889; //SQLSTATE: HY000 Message: Statement is unsafe because it uses a fulltext parser plugin which may not return the same value on the slave.; was introduced in 5.7.1. + public final static int ER_CANNOT_DISCARD_TEMPORARY_TABLE = 1890; //SQLSTATE: HY000 Message: Cannot DISCARD/IMPORT tablespace associated with temporary table; was introduced in 5.7.1. + public final static int ER_FK_DEPTH_EXCEEDED = 1891; //SQLSTATE: HY000 Message: Foreign key cascade delete/update exceeds max depth of %d.; was introduced in 5.7.2. + public final static int ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 = 1892; //SQLSTATE: HY000 Message: Column count of %s.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysql_upgrade to fix this error.; was introduced in 5.7.2. + public final static int ER_WARN_TRIGGER_DOESNT_HAVE_CREATED = 1893; //SQLSTATE: HY000 Message: Trigger %s.%s.%s does not have CREATED attribute.; was introduced in 5.7.2. + public final static int ER_REFERENCED_TRG_DOES_NOT_EXIST = 1894; //SQLSTATE: HY000 Message: Referenced trigger '%s' for the given action time and event type does not exist.; was introduced in 5.7.2. + public final static int ER_EXPLAIN_NOT_SUPPORTED = 1895; //SQLSTATE: HY000 Message: EXPLAIN FOR CONNECTION command is supported only for SELECT/UPDATE/INSERT/DELETE/REPLACE; was introduced in 5.7.2. + public final static int ER_INVALID_FIELD_SIZE = 1896; //SQLSTATE: HY000 Message: Invalid size for column '%s'.; was introduced in 5.7.2. + public final static int ER_MISSING_HA_CREATE_OPTION = 1897; //SQLSTATE: HY000 Message: Table storage engine '%s' found required create option missing; was introduced in 5.7.2. + public final static int ER_ENGINE_OUT_OF_MEMORY = 1898; //SQLSTATE: HY000 Message: Out of memory in storage engine '%s'.; was introduced in 5.7.3. + public final static int ER_PASSWORD_EXPIRE_ANONYMOUS_USER = 1899; //SQLSTATE: HY000 Message: The password for anonymous user cannot be expired.; was introduced in 5.7.3. + public final static int ER_SLAVE_SQL_THREAD_MUST_STOP = 1900; //SQLSTATE: HY000 Message: This operation cannot be performed with a running slave sql thread; run STOP SLAVE SQL_THREAD first; was introduced in 5.7.3. + public final static int ER_NO_FT_MATERIALIZED_SUBQUERY = 1901; //SQLSTATE: HY000 Message: Cannot create FULLTEXT index on materialized subquery; was introduced in 5.7.4. + public final static int ER_INNODB_UNDO_LOG_FULL = 1902; //SQLSTATE: HY000 Message: Undo Log error: %s; was introduced in 5.7.4. + public final static int ER_INVALID_ARGUMENT_FOR_LOGARITHM = 1903; //SQLSTATE: 2201E Message: Invalid argument for logarithm; was introduced in 5.7.4. + public final static int ER_SLAVE_IO_THREAD_MUST_STOP = 1904; //SQLSTATE: HY000 Message: This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD first.; was introduced in 5.7.4. + public final static int ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO = 1905; //SQLSTATE: HY000 Message: This operation may not be safe when the slave has temporary tables. The tables will be kept open until the server restarts or until the tables are deleted by any replicated DROP statement. Suggest to wait until slave_open_temp_tables = 0.; was introduced in 5.7.4. + public final static int ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS = 1906; //SQLSTATE: HY000 Message: CHANGE MASTER TO with a MASTER_LOG_FILE clause but no MASTER_LOG_POS clause may not be safe. The old position value may not be valid for the new binary log file.; was introduced in 5.7.4. + public final static int ER_QUERY_TIMEOUT = 1907; //SQLSTATE: HY000 Message: Query execution was interrupted, max_statement_time exceeded; was introduced in 5.7.4. + public final static int ER_NON_RO_SELECT_DISABLE_TIMER = 1908; //SQLSTATE: HY000 Message: Select is not a read only statement, disabling timer; was introduced in 5.7.4. + public final static int ER_DUP_LIST_ENTRY = 1909; //SQLSTATE: HY000 Message: Duplicate entry '%s'.; was introduced in 5.7.4. + public final static int ER_SQL_MODE_NO_EFFECT = 1910; //SQLSTATE: HY000 Message: '%s' mode no longer has any effect. Use STRICT_ALL_TABLES or STRICT_TRANS_TABLES instead.; was introduced in 5.7.4. - public final static int ER_AUTO_CONVERT = 1246; - - public final static int ER_BAD_DB_ERROR = 1049; - - public final static int ER_BAD_FIELD_ERROR = 1054; - - public final static int ER_BAD_FT_COLUMN = 1283; - - public final static int ER_BAD_HOST_ERROR = 1042; - - public final static int ER_BAD_NULL_ERROR = 1048; - - public final static int ER_BAD_SLAVE = 1200; - - public final static int ER_BAD_SLAVE_UNTIL_COND = 1277; - - public final static int ER_BAD_TABLE_ERROR = 1051; - - public final static int ER_BLOB_CANT_HAVE_DEFAULT = 1101; - - public final static int ER_BLOB_KEY_WITHOUT_LENGTH = 1170; - - public final static int ER_BLOB_USED_AS_KEY = 1073; - - public final static int ER_BLOBS_AND_NO_TERMINATED = 1084; - - public final static int ER_CANNOT_ADD_FOREIGN = 1215; - - public final static int ER_CANT_AGGREGATE_2COLLATIONS = 1267; - - public final static int ER_CANT_AGGREGATE_3COLLATIONS = 1270; - - public final static int ER_CANT_AGGREGATE_NCOLLATIONS = 1271; - - public final static int ER_CANT_CREATE_DB = 1006; - - public final static int ER_CANT_CREATE_FILE = 1004; - - public final static int ER_CANT_CREATE_TABLE = 1005; - - public final static int ER_CANT_CREATE_THREAD = 1135; - - public final static int ER_CANT_DELETE_FILE = 1011; - - public final static int ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179; - - public final static int ER_CANT_DROP_FIELD_OR_KEY = 1091; - - public final static int ER_CANT_FIND_DL_ENTRY = 1127; - - public final static int ER_CANT_FIND_SYSTEM_REC = 1012; - - public final static int ER_CANT_FIND_UDF = 1122; - - public final static int ER_CANT_GET_STAT = 1013; - - public final static int ER_CANT_GET_WD = 1014; - - public final static int ER_CANT_INITIALIZE_UDF = 1123; - - public final static int ER_CANT_LOCK = 1015; - - public final static int ER_CANT_OPEN_FILE = 1016; - - public final static int ER_CANT_OPEN_LIBRARY = 1126; - - public final static int ER_CANT_READ_DIR = 1018; - - public final static int ER_CANT_REMOVE_ALL_FIELDS = 1090; - - public final static int ER_CANT_REOPEN_TABLE = 1137; - - public final static int ER_CANT_SET_WD = 1019; - - public final static int ER_CANT_UPDATE_WITH_READLOCK = 1223; - - public final static int ER_CANT_USE_OPTION_HERE = 1234; - - public final static int ER_CHECK_NO_SUCH_TABLE = 1177; - - public final static int ER_CHECK_NOT_IMPLEMENTED = 1178; - - public final static int ER_CHECKREAD = 1020; - - public final static int ER_COLLATION_CHARSET_MISMATCH = 1253; - - public final static int ER_COLUMNACCESS_DENIED_ERROR = 1143; - - public final static int ER_CON_COUNT_ERROR = 1040; - - public final static int ER_CONNECT_TO_MASTER = 1218; - - public final static int ER_CORRUPT_HELP_DB = 1244; - - public final static int ER_CRASHED_ON_REPAIR = 1195; - - public final static int ER_CRASHED_ON_USAGE = 1194; - - public final static int ER_CREATE_DB_WITH_READ_LOCK = 1209; - - public final static int ER_CUT_VALUE_GROUP_CONCAT = 1260; - - public final static int ER_CYCLIC_REFERENCE = 1245; - - public final static int ER_DB_CREATE_EXISTS = 1007; - - public final static int ER_DB_DROP_DELETE = 1009; - - public final static int ER_DB_DROP_EXISTS = 1008; - - public final static int ER_DB_DROP_RMDIR = 1010; - - public final static int ER_DBACCESS_DENIED_ERROR = 1044; - - public final static int ER_DELAYED_CANT_CHANGE_LOCK = 1150; - - public final static int ER_DELAYED_INSERT_TABLE_LOCKED = 1165; - - public final static int ER_DERIVED_MUST_HAVE_ALIAS = 1248; - - public final static int ER_DISK_FULL = 1021; - - public final static int ER_DROP_DB_WITH_READ_LOCK = 1208; - - public final static int ER_DROP_USER = 1268; - - public final static int ER_DUMP_NOT_IMPLEMENTED = 1185; - - public final static int ER_DUP_ARGUMENT = 1225; - - public final static int ER_DUP_ENTRY = 1062; - - public final static int ER_DUP_FIELDNAME = 1060; - - public final static int ER_DUP_KEY = 1022; - - public final static int ER_DUP_KEYNAME = 1061; - - public final static int ER_DUP_UNIQUE = 1169; - - public final static int ER_DUPLICATED_VALUE_IN_TYPE = 1291; - - public final static int ER_EMPTY_QUERY = 1065; - - public final static int ER_ERROR_DURING_CHECKPOINT = 1183; - - public final static int ER_ERROR_DURING_COMMIT = 1180; - - public final static int ER_ERROR_DURING_FLUSH_LOGS = 1182; - - public final static int ER_ERROR_DURING_ROLLBACK = 1181; - - public final static int ER_ERROR_MESSAGES = 298; - - public final static int ER_ERROR_ON_CLOSE = 1023; - - public final static int ER_ERROR_ON_READ = 1024; - - public final static int ER_ERROR_ON_RENAME = 1025; - - public final static int ER_ERROR_ON_WRITE = 1026; - - public final static int ER_ERROR_WHEN_EXECUTING_COMMAND = 1220; - - public final static int ER_FEATURE_DISABLED = 1289; - - public final static int ER_FIELD_SPECIFIED_TWICE = 1110; - - public final static int ER_FILE_EXISTS_ERROR = 1086; - - public final static int ER_FILE_NOT_FOUND = 1017; - - public final static int ER_FILE_USED = 1027; - - public final static int ER_FILSORT_ABORT = 1028; - - public final static int ER_FLUSH_MASTER_BINLOG_CLOSED = 1186; - - public final static int ER_FORCING_CLOSE = 1080; - - public final static int ER_FORM_NOT_FOUND = 1029; - - public final static int ER_FT_MATCHING_KEY_NOT_FOUND = 1191; - - public final static int ER_FUNCTION_NOT_DEFINED = 1128; - - public final static int ER_GET_ERRMSG = 1296; - - public final static int ER_GET_ERRNO = 1030; - - public final static int ER_GET_TEMPORARY_ERRMSG = 1297; - - public final static int ER_GLOBAL_VARIABLE = 1229; - - public final static int ER_GOT_SIGNAL = 1078; - - public final static int ER_GRANT_WRONG_HOST_OR_USER = 1145; - - public final static int ER_HANDSHAKE_ERROR = 1043; - - public final static int ER_HASHCHK = 1000; - - public final static int ER_HOST_IS_BLOCKED = 1129; - - public final static int ER_HOST_NOT_PRIVILEGED = 1130; - - public final static int ER_ILLEGAL_GRANT_FOR_TABLE = 1144; - - public final static int ER_ILLEGAL_HA = 1031; - - public final static int ER_ILLEGAL_REFERENCE = 1247; - - public final static int ER_INCORRECT_GLOBAL_LOCAL_VAR = 1238; - - public final static int ER_INDEX_REBUILD = 1187; - - public final static int ER_INSERT_INFO = 1092; - - public final static int ER_INVALID_DEFAULT = 1067; - - public final static int ER_INVALID_GROUP_FUNC_USE = 1111; - - public final static int ER_INVALID_ON_UPDATE = 1294; - - public final static int ER_INVALID_USE_OF_NULL = 1138; - - public final static int ER_IPSOCK_ERROR = 1081; - - public final static int ER_KEY_COLUMN_DOES_NOT_EXITS = 1072; - - public final static int ER_KEY_DOES_NOT_EXITS = 1176; - - public final static int ER_KEY_NOT_FOUND = 1032; - - public final static int ER_KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240; - - public final static int ER_KILL_DENIED_ERROR = 1095; - - public final static int ER_LOAD_INFO = 1087; - - public final static int ER_LOCAL_VARIABLE = 1228; - - public final static int ER_LOCK_DEADLOCK = 1213; - - public final static int ER_LOCK_OR_ACTIVE_TRANSACTION = 1192; - - public final static int ER_LOCK_TABLE_FULL = 1206; - - public final static int ER_LOCK_WAIT_TIMEOUT = 1205; - - public final static int ER_MASTER = 1188; - - public final static int ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236; - - public final static int ER_MASTER_INFO = 1201; - - public final static int ER_MASTER_NET_READ = 1189; - - public final static int ER_MASTER_NET_WRITE = 1190; - - public final static int ER_MISSING_SKIP_SLAVE = 1278; - - public final static int ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140; - - public final static int ER_MIXING_NOT_ALLOWED = 1224; - - public final static int ER_MULTIPLE_PRI_KEY = 1068; - - public final static int ER_NET_ERROR_ON_WRITE = 1160; - - public final static int ER_NET_FCNTL_ERROR = 1155; - - public final static int ER_NET_PACKET_TOO_LARGE = 1153; - - public final static int ER_NET_PACKETS_OUT_OF_ORDER = 1156; - - public final static int ER_NET_READ_ERROR = 1158; - - public final static int ER_NET_READ_ERROR_FROM_PIPE = 1154; - - public final static int ER_NET_READ_INTERRUPTED = 1159; - - public final static int ER_NET_UNCOMPRESS_ERROR = 1157; - - public final static int ER_NET_WRITE_INTERRUPTED = 1161; - - public final static int ER_NEW_ABORTING_CONNECTION = 1184; - - public final static int ER_NISAMCHK = 1001; - - public final static int ER_NO = 1002; - - public final static int ER_NO_DB_ERROR = 1046; - - public final static int ER_NO_DEFAULT = 1230; - - public final static int ER_NO_PERMISSION_TO_CREATE_USER = 1211; - - public final static int ER_NO_RAID_COMPILED = 1174; - - public final static int ER_NO_REFERENCED_ROW = 1216; - - public final static int ER_NO_SUCH_INDEX = 1082; - - public final static int ER_NO_SUCH_TABLE = 1146; - - public final static int ER_NO_SUCH_THREAD = 1094; - - public final static int ER_NO_TABLES_USED = 1096; - - public final static int ER_NO_UNIQUE_LOGFILE = 1098; - - public final static int ER_NON_UNIQ_ERROR = 1052; - - public final static int ER_NON_UPDATABLE_TABLE = 1288; - - public final static int ER_NONEXISTING_GRANT = 1141; - - public final static int ER_NONEXISTING_TABLE_GRANT = 1147; - - public final static int ER_NONUNIQ_TABLE = 1066; - - public final static int ER_NORMAL_SHUTDOWN = 1077; - - public final static int ER_NOT_ALLOWED_COMMAND = 1148; - - public final static int ER_NOT_FORM_FILE = 1033; - - public final static int ER_NOT_KEYFILE = 1034; - - public final static int ER_NOT_SUPPORTED_AUTH_MODE = 1251; - - public final static int ER_NOT_SUPPORTED_YET = 1235; - - public final static int ER_NULL_COLUMN_IN_INDEX = 1121; - - public final static int ER_OLD_KEYFILE = 1035; - - public final static int ER_OPEN_AS_READONLY = 1036; - - public final static int ER_OPERAND_COLUMNS = 1241; - - public final static int ER_OPTION_PREVENTS_STATEMENT = 1290; - - public final static int ER_OUT_OF_RESOURCES = 1041; - - public final static int ER_OUT_OF_SORTMEMORY = 1038; - - public final static int ER_OUTOFMEMORY = 1037; - - public final static int ER_PARSE_ERROR = 1064; - - public final static int ER_PASSWORD_ANONYMOUS_USER = 1131; - - public final static int ER_PASSWORD_NO_MATCH = 1133; - - public final static int ER_PASSWORD_NOT_ALLOWED = 1132; - - public final static int ER_PRIMARY_CANT_HAVE_NULL = 1171; - - public final static int ER_QUERY_ON_MASTER = 1219; - - public final static int ER_READ_ONLY_TRANSACTION = 1207; - - public final static int ER_READY = 1076; - - public final static int ER_RECORD_FILE_FULL = 1114; - - public final static int ER_REGEXP_ERROR = 1139; - - public final static int ER_REQUIRES_PRIMARY_KEY = 1173; - - public final static int ER_REVOKE_GRANTS = 1269; - - public final static int ER_ROW_IS_REFERENCED = 1217; - - public final static int ER_SELECT_REDUCED = 1249; - - public final static int ER_SERVER_IS_IN_SECURE_AUTH_MODE = 1275; - - public final static int ER_SERVER_SHUTDOWN = 1053; - - public final static int ER_SET_CONSTANTS_ONLY = 1204; - - public final static int ER_SHUTDOWN_COMPLETE = 1079; - - public final static int ER_SLAVE_IGNORED_SSL_PARAMS = 1274; - - public final static int ER_SLAVE_IGNORED_TABLE = 1237; - - public final static int ER_SLAVE_MUST_STOP = 1198; - - public final static int ER_SLAVE_NOT_RUNNING = 1199; - - public final static int ER_SLAVE_THREAD = 1202; - - public final static int ER_SLAVE_WAS_NOT_RUNNING = 1255; - - public final static int ER_SLAVE_WAS_RUNNING = 1254; - - public final static int ER_SPATIAL_CANT_HAVE_NULL = 1252; - - public final static int ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227; - - public final static int ER_STACK_OVERRUN = 1119; - - public final static int ER_SUBQUERY_NO_1_ROW = 1242; - - public final static int ER_SYNTAX_ERROR = 1149; - - public final static int ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164; - - public final static int ER_TABLE_CANT_HANDLE_BLOB = 1163; - - public final static int ER_TABLE_CANT_HANDLE_FT = 1214; - - public final static int ER_TABLE_EXISTS_ERROR = 1050; - - public final static int ER_TABLE_MUST_HAVE_COLUMNS = 1113; - - public final static int ER_TABLE_NOT_LOCKED = 1100; - - public final static int ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099; - - public final static int ER_TABLEACCESS_DENIED_ERROR = 1142; - - public final static int ER_TABLENAME_NOT_ALLOWED_HERE = 1250; - - public final static int ER_TEXTFILE_NOT_READABLE = 1085; - - public final static int ER_TOO_BIG_FIELDLENGTH = 1074; - - public final static int ER_TOO_BIG_FOR_UNCOMPRESS = 1256; - - public final static int ER_TOO_BIG_ROWSIZE = 1118; - - public final static int ER_TOO_BIG_SELECT = 1104; - - public final static int ER_TOO_BIG_SET = 1097; - - public final static int ER_TOO_LONG_IDENT = 1059; - - public final static int ER_TOO_LONG_KEY = 1071; - - public final static int ER_TOO_LONG_STRING = 1162; - - public final static int ER_TOO_MANY_DELAYED_THREADS = 1151; - - public final static int ER_TOO_MANY_FIELDS = 1117; - - public final static int ER_TOO_MANY_KEY_PARTS = 1070; - - public final static int ER_TOO_MANY_KEYS = 1069; - - public final static int ER_TOO_MANY_ROWS = 1172; - - public final static int ER_TOO_MANY_TABLES = 1116; - - public final static int ER_TOO_MANY_USER_CONNECTIONS = 1203; - - public final static int ER_TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293; - - public final static int ER_TRANS_CACHE_FULL = 1197; - - public final static int ER_TRUNCATED_WRONG_VALUE = 1292; - - public final static int ER_UDF_EXISTS = 1125; - - public final static int ER_UDF_NO_PATHS = 1124; - - public final static int ER_UNEXPECTED_EOF = 1039; - - public final static int ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212; - - public final static int ER_UNKNOWN_CHARACTER_SET = 1115; - - public final static int ER_UNKNOWN_COLLATION = 1273; - - public final static int ER_UNKNOWN_COM_ERROR = 1047; - - public final static int ER_UNKNOWN_ERROR = 1105; - - public final static int ER_UNKNOWN_KEY_CACHE = 1284; - - public final static int ER_UNKNOWN_PROCEDURE = 1106; - - public final static int ER_UNKNOWN_STMT_HANDLER = 1243; - - public final static int ER_UNKNOWN_STORAGE_ENGINE = 1286; - - public final static int ER_UNKNOWN_SYSTEM_VARIABLE = 1193; - - public final static int ER_UNKNOWN_TABLE = 1109; - - public final static int ER_UNSUPPORTED_EXTENSION = 1112; - - public final static int ER_UNSUPPORTED_PS = 1295; - - public final static int ER_UNTIL_COND_IGNORED = 1279; - - public final static int ER_UPDATE_INFO = 1134; - - public final static int ER_UPDATE_TABLE_USED = 1093; - - public final static int ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175; - - public final static int ER_USER_LIMIT_REACHED = 1226; - - public final static int ER_VAR_CANT_BE_READ = 1233; - - public final static int ER_VARIABLE_IS_NOT_STRUCT = 1272; - - public final static int ER_WARN_DATA_OUT_OF_RANGE = 1264; - - public final static int ER_WARN_DATA_TRUNCATED = 1265; - - public final static int ER_WARN_DEPRECATED_SYNTAX = 1287; - - public final static int ER_WARN_FIELD_RESOLVED = 1276; - - public final static int ER_WARN_HOSTNAME_WONT_WORK = 1285; - - public final static int ER_WARN_NULL_TO_NOTNULL = 1263; - - public final static int ER_WARN_QC_RESIZE = 1282; - - public final static int ER_WARN_TOO_FEW_RECORDS = 1261; - - public final static int ER_WARN_TOO_MANY_RECORDS = 1262; - - public final static int ER_WARN_USING_OTHER_HANDLER = 1266; - - public final static int ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196; - - public final static int ER_WRONG_ARGUMENTS = 1210; - - public final static int ER_WRONG_AUTO_KEY = 1075; - - public final static int ER_WRONG_COLUMN_NAME = 1166; - - public final static int ER_WRONG_DB_NAME = 1102; - - public final static int ER_WRONG_FIELD_SPEC = 1063; - - public final static int ER_WRONG_FIELD_TERMINATORS = 1083; - - public final static int ER_WRONG_FIELD_WITH_GROUP = 1055; - - public final static int ER_WRONG_FK_DEF = 1239; - - public final static int ER_WRONG_GROUP_FIELD = 1056; - - public final static int ER_WRONG_KEY_COLUMN = 1167; - - public final static int ER_WRONG_MRG_TABLE = 1168; - - public final static int ER_WRONG_NAME_FOR_CATALOG = 1281; - - public final static int ER_WRONG_NAME_FOR_INDEX = 1280; - - public final static int ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222; - - public final static int ER_WRONG_OUTER_JOIN = 1120; - - public final static int ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107; - - public final static int ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108; - - public final static int ER_WRONG_SUB_KEY = 1089; - - public final static int ER_WRONG_SUM_SELECT = 1057; - - public final static int ER_WRONG_TABLE_NAME = 1103; - - public final static int ER_WRONG_TYPE_FOR_VAR = 1232; - - public final static int ER_WRONG_USAGE = 1221; - - public final static int ER_WRONG_VALUE_COUNT = 1058; - - public final static int ER_WRONG_VALUE_COUNT_ON_ROW = 1136; - - public final static int ER_WRONG_VALUE_FOR_VAR = 1231; - - public final static int ER_XA_RMERR = 1401; - - public final static int ER_YES = 1003; - - public final static int ER_ZLIB_Z_BUF_ERROR = 1258; - - public final static int ER_ZLIB_Z_DATA_ERROR = 1259; - - public final static int ER_ZLIB_Z_MEM_ERROR = 1257; - private MysqlErrorNumbers() { // prevent instantiation } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlIO.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlIO.java (.../MysqlIO.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlIO.java (.../MysqlIO.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.BufferedInputStream; @@ -32,25 +31,38 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; import java.lang.ref.SoftReference; -import java.lang.reflect.Method; import java.math.BigInteger; import java.net.MalformedURLException; import java.net.Socket; +import java.net.SocketException; import java.net.URL; -import java.nio.ByteBuffer; import java.security.NoSuchAlgorithmException; +import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Types; import java.util.ArrayList; -import java.util.Calendar; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.zip.Deflater; -import com.mysql.jdbc.profiler.ProfileEventSink; +import com.mysql.jdbc.authentication.MysqlClearPasswordPlugin; +import com.mysql.jdbc.authentication.MysqlNativePasswordPlugin; +import com.mysql.jdbc.authentication.MysqlOldPasswordPlugin; +import com.mysql.jdbc.authentication.Sha256PasswordPlugin; +import com.mysql.jdbc.exceptions.MySQLStatementCancelledException; +import com.mysql.jdbc.exceptions.MySQLTimeoutException; +import com.mysql.jdbc.log.LogUtils; import com.mysql.jdbc.profiler.ProfilerEvent; +import com.mysql.jdbc.profiler.ProfilerEventHandler; import com.mysql.jdbc.util.ReadAheadInputStream; import com.mysql.jdbc.util.ResultSetUtil; @@ -63,38 +75,43 @@ * * @see java.sql.Connection */ -class MysqlIO { - protected static final int NULL_LENGTH = ~0; +public class MysqlIO { + private static final int UTF8_CHARSET_INDEX = 33; + private static final String CODE_PAGE_1252 = "Cp1252"; + protected static final int NULL_LENGTH = ~0; protected static final int COMP_HEADER_LENGTH = 3; protected static final int MIN_COMPRESS_LEN = 50; protected static final int HEADER_LENGTH = 4; protected static final int AUTH_411_OVERHEAD = 33; private static int maxBufferSize = 65535; - private static final int CLIENT_COMPRESS = 32; /* Can use compression - protcol */ - protected static final int CLIENT_CONNECT_WITH_DB = 8; - private static final int CLIENT_FOUND_ROWS = 2; - private static final int CLIENT_LOCAL_FILES = 128; /* Can use LOAD DATA - LOCAL */ - /* Found instead of - affected rows */ - private static final int CLIENT_LONG_FLAG = 4; /* Get all column flags */ - private static final int CLIENT_LONG_PASSWORD = 1; /* new more secure - passwords */ - private static final int CLIENT_PROTOCOL_41 = 512; // for > 4.1.1 - private static final int CLIENT_INTERACTIVE = 1024; - protected static final int CLIENT_SSL = 2048; - private static final int CLIENT_TRANSACTIONS = 8192; // Client knows about transactions - protected static final int CLIENT_RESERVED = 16384; // for 4.1.0 only - protected static final int CLIENT_SECURE_CONNECTION = 32768; - private static final int CLIENT_MULTI_QUERIES = 65536; // Enable/disable multiquery support - private static final int CLIENT_MULTI_RESULTS = 131072; // Enable/disable multi-results - private static final int SERVER_STATUS_IN_TRANS = 1; + private static final String NONE = "none"; + + private static final int CLIENT_LONG_PASSWORD = 0x00000001; /* new more secure passwords */ + private static final int CLIENT_FOUND_ROWS = 0x00000002; + private static final int CLIENT_LONG_FLAG = 0x00000004; /* Get all column flags */ + protected static final int CLIENT_CONNECT_WITH_DB = 0x00000008; + private static final int CLIENT_COMPRESS = 0x00000020; /* Can use compression protcol */ + private static final int CLIENT_LOCAL_FILES = 0x00000080; /* Can use LOAD DATA LOCAL */ + private static final int CLIENT_PROTOCOL_41 = 0x00000200; // for > 4.1.1 + private static final int CLIENT_INTERACTIVE = 0x00000400; + protected static final int CLIENT_SSL = 0x00000800; + private static final int CLIENT_TRANSACTIONS = 0x00002000; // Client knows about transactions + protected static final int CLIENT_RESERVED = 0x00004000; // for 4.1.0 only + protected static final int CLIENT_SECURE_CONNECTION = 0x00008000; + private static final int CLIENT_MULTI_STATEMENTS = 0x00010000; // Enable/disable multiquery support + private static final int CLIENT_MULTI_RESULTS = 0x00020000; // Enable/disable multi-results + private static final int CLIENT_PLUGIN_AUTH = 0x00080000; + private static final int CLIENT_CONNECT_ATTRS = 0x00100000; + private static final int CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000; + private static final int CLIENT_CAN_HANDLE_EXPIRED_PASSWORD = 0x00400000; + + private static final int SERVER_STATUS_IN_TRANS = 1; private static final int SERVER_STATUS_AUTOCOMMIT = 2; // Server in auto_commit mode - private static final int SERVER_MORE_RESULTS_EXISTS = 8; // Multi query - next query exists + static final int SERVER_MORE_RESULTS_EXISTS = 8; // Multi query - next query exists private static final int SERVER_QUERY_NO_GOOD_INDEX_USED = 16; private static final int SERVER_QUERY_NO_INDEX_USED = 32; + private static final int SERVER_QUERY_WAS_SLOW = 2048; private static final int SERVER_STATUS_CURSOR_EXISTS = 64; private static final String FALSE_SCRAMBLE = "xxxxxxxx"; //$NON-NLS-1$ protected static final int MAX_QUERY_SIZE_TO_LOG = 1024; // truncate logging of queries at 1K @@ -105,11 +122,6 @@ * filenames for LOAD DATA LOCAL INFILE... */ private static String jvmPlatformCharset = null; - - /** - * Are we using packed or unpacked binary result set rows? - */ - private boolean binaryResultsAreUnpacked = true; /** * We need to have a 'marker' for all-zero datetimes so that ResultSet @@ -118,7 +130,11 @@ protected final static String ZERO_DATE_VALUE_MARKER = "0000-00-00"; protected final static String ZERO_DATETIME_VALUE_MARKER = "0000-00-00 00:00:00"; - static { + private static final String EXPLAINABLE_STATEMENT = "SELECT"; + private static final String[] EXPLAINABLE_STATEMENT_EXTENSION = new String[] { "INSERT", "UPDATE", "REPLACE", + "DELETE" }; + + static { OutputStreamWriter outWriter = null; // @@ -156,30 +172,31 @@ /** Data to the server */ protected BufferedOutputStream mysqlOutput = null; - protected com.mysql.jdbc.Connection connection; + protected MySQLConnection connection; private Deflater deflater = null; protected InputStream mysqlInput = null; - private LinkedList packetDebugRingBuffer = null; + private LinkedList packetDebugRingBuffer = null; private RowData streamingData = null; /** The connection to the server */ - protected Socket mysqlConnection = null; - private SocketFactory socketFactory = null; + public Socket mysqlConnection = null; + protected SocketFactory socketFactory = null; // // Packet used for 'LOAD DATA LOCAL INFILE' // // We use a SoftReference, so that we don't penalize intermittent // use of this feature // - private SoftReference loadFileBufRef; + private SoftReference loadFileBufRef; // // Used to send large packets to the server versions 4+ // We use a SoftReference, so that we don't penalize intermittent // use of this feature // - private SoftReference splitBufRef; + private SoftReference splitBufRef; + private SoftReference compressBufRef; protected String host = null; protected String seed; private String serverVersion = null; @@ -202,37 +219,46 @@ private boolean profileSql = false; private boolean queryBadIndexUsed = false; private boolean queryNoIndexUsed = false; + private boolean serverQueryWasSlow = false; /** Should we use 4.1 protocol extensions? */ private boolean use41Extensions = false; private boolean useCompression = false; private boolean useNewLargePackets = false; private boolean useNewUpdateCounts = false; // should we use the new larger update counts? private byte packetSequence = 0; + private byte compressedPacketSequence = 0; private byte readPacketSequence = -1; private boolean checkPacketSequence = false; - byte protocolVersion = 0; + private byte protocolVersion = 0; private int maxAllowedPacket = 1024 * 1024; protected int maxThreeBytes = 255 * 255 * 255; protected int port = 3306; protected int serverCapabilities; private int serverMajorVersion = 0; private int serverMinorVersion = 0; + private int oldServerStatus = 0; private int serverStatus = 0; private int serverSubMinorVersion = 0; private int warningCount = 0; protected long clientParam = 0; protected long lastPacketSentTimeMs = 0; + protected long lastPacketReceivedTimeMs = 0; private boolean traceProtocol = false; private boolean enablePacketDebug = false; - private Calendar sessionCalendar; private boolean useConnectWithDb; private boolean needToGrabQueryFromPacket; private boolean autoGenerateTestcaseScript; private long threadId; private boolean useNanosForElapsedTime; private long slowQueryThreshold; private String queryTimingUnits; + private boolean useDirectRowUnpack = true; + private int useBufferRowSizeThreshold; + private int commandCount = 0; + private List statementInterceptors; + private ExceptionInterceptor exceptionInterceptor; + private int authPluginDataLength = 0; /** * Constructor: Connect to the MySQL server and setup a stream connection. @@ -249,76 +275,88 @@ * @throws SQLException if a database access error occurs. */ public MysqlIO(String host, int port, Properties props, - String socketFactoryClassName, com.mysql.jdbc.Connection conn, - int socketTimeout) throws IOException, SQLException { - this.connection = conn; + String socketFactoryClassName, MySQLConnection conn, + int socketTimeout, int useBufferRowSizeThreshold) throws IOException, SQLException { + this.connection = conn; + + if (this.connection.getEnablePacketDebug()) { + this.packetDebugRingBuffer = new LinkedList(); + } + this.traceProtocol = this.connection.getTraceProtocol(); + - if (this.connection.getEnablePacketDebug()) { - this.packetDebugRingBuffer = new LinkedList(); - } + this.useAutoSlowLog = this.connection.getAutoSlowLog(); + + this.useBufferRowSizeThreshold = useBufferRowSizeThreshold; + this.useDirectRowUnpack = this.connection.getUseDirectRowUnpack(); - this.logSlowQueries = this.connection.getLogSlowQueries(); + this.logSlowQueries = this.connection.getLogSlowQueries(); - this.reusablePacket = new Buffer(INITIAL_PACKET_SIZE); - this.sendPacket = new Buffer(INITIAL_PACKET_SIZE); + this.reusablePacket = new Buffer(INITIAL_PACKET_SIZE); + this.sendPacket = new Buffer(INITIAL_PACKET_SIZE); - this.port = port; - this.host = host; + this.port = port; + this.host = host; - this.socketFactoryClassName = socketFactoryClassName; - this.socketFactory = createSocketFactory(); - - this.mysqlConnection = this.socketFactory.connect(this.host, this.port, - props); - - if (socketTimeout != 0) { - try { - this.mysqlConnection.setSoTimeout(socketTimeout); - } catch (Exception ex) { - /* Ignore if the platform does not support it */ - ; + this.socketFactoryClassName = socketFactoryClassName; + this.socketFactory = createSocketFactory(); + this.exceptionInterceptor = this.connection.getExceptionInterceptor(); + + try { + this.mysqlConnection = this.socketFactory.connect(this.host, + this.port, props); + + + if (socketTimeout != 0) { + try { + this.mysqlConnection.setSoTimeout(socketTimeout); + } catch (Exception ex) { + /* Ignore if the platform does not support it */ + } + } + + this.mysqlConnection = this.socketFactory.beforeHandshake(); + + if (this.connection.getUseReadAheadInput()) { + this.mysqlInput = new ReadAheadInputStream(this.mysqlConnection.getInputStream(), 16384, + this.connection.getTraceProtocol(), + this.connection.getLog()); + } else if (this.connection.useUnbufferedInput()) { + this.mysqlInput = this.mysqlConnection.getInputStream(); + } else { + this.mysqlInput = new BufferedInputStream(this.mysqlConnection.getInputStream(), + 16384); + } + + this.mysqlOutput = new BufferedOutputStream(this.mysqlConnection.getOutputStream(), + 16384); + + + this.isInteractiveClient = this.connection.getInteractiveClient(); + this.profileSql = this.connection.getProfileSql(); + this.autoGenerateTestcaseScript = this.connection.getAutoGenerateTestcaseScript(); + + this.needToGrabQueryFromPacket = (this.profileSql || + this.logSlowQueries || + this.autoGenerateTestcaseScript); + + if (this.connection.getUseNanosForElapsedTime() + && Util.nanoTimeAvailable()) { + this.useNanosForElapsedTime = true; + + this.queryTimingUnits = Messages.getString("Nanoseconds"); + } else { + this.queryTimingUnits = Messages.getString("Milliseconds"); } - } + + if (this.connection.getLogSlowQueries()) { + calculateSlowQueryThreshold(); + } + } catch (IOException ioEx) { + throw SQLError.createCommunicationsException(this.connection, 0, 0, ioEx, getExceptionInterceptor()); + } + } - this.mysqlConnection = this.socketFactory.beforeHandshake(); - - if (this.connection.getUseReadAheadInput()) { - this.mysqlInput = new ReadAheadInputStream(this.mysqlConnection - .getInputStream(), 16384, this.connection - .getTraceProtocol(), this.connection.getLog()); - } else if (this.connection.useUnbufferedInput()) { - this.mysqlInput = this.mysqlConnection.getInputStream(); - } else { - this.mysqlInput = new BufferedInputStream(this.mysqlConnection - .getInputStream(), 16384); - } - - this.mysqlOutput = new BufferedOutputStream(this.mysqlConnection - .getOutputStream(), 16384); - - this.isInteractiveClient = this.connection.getInteractiveClient(); - this.profileSql = this.connection.getProfileSql(); - this.sessionCalendar = Calendar.getInstance(); - this.autoGenerateTestcaseScript = this.connection - .getAutoGenerateTestcaseScript(); - - this.needToGrabQueryFromPacket = (this.profileSql - || this.logSlowQueries || this.autoGenerateTestcaseScript); - - if (this.connection.getUseNanosForElapsedTime() - && Util.nanoTimeAvailable()) { - this.useNanosForElapsedTime = true; - - this.queryTimingUnits = Messages.getString("Nanoseconds"); - } else { - this.queryTimingUnits = Messages.getString("Milliseconds"); - } - - if (this.connection.getLogSlowQueries()) { - calculateSlowQueryThreshold(); - } - } - /** * Does the server send back extra column info? * @@ -332,8 +370,8 @@ try { return this.mysqlInput.available() > 0; } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } } @@ -345,6 +383,10 @@ protected long getLastPacketSentTimeMs() { return this.lastPacketSentTimeMs; } + + protected long getLastPacketReceivedTimeMs() { + return this.lastPacketReceivedTimeMs; + } /** * Build a result set. Delegates to buildResultSetWithRows() to build a @@ -367,142 +409,127 @@ * * @throws SQLException if a database access error occurs */ - protected ResultSet getResultSet(Statement callingStatement, + protected ResultSetImpl getResultSet(StatementImpl callingStatement, long columnCount, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, - boolean isBinaryEncoded, boolean unpackFieldInfo, Field[] metadataFromCache) + boolean isBinaryEncoded, Field[] metadataFromCache) throws SQLException { Buffer packet; // The packet from the server Field[] fields = null; // Read in the column information - - if (unpackFieldInfo) { + + if (metadataFromCache == null /* we want the metadata from the server */) { fields = new Field[(int) columnCount]; - + for (int i = 0; i < columnCount; i++) { Buffer fieldPacket = null; - + fieldPacket = readPacket(); fields[i] = unpackField(fieldPacket, false); } } else { for (int i = 0; i < columnCount; i++) { skipPacket(); } - - //this.reusablePacket.clear(); } packet = reuseAndReadPacket(this.reusablePacket); - + readServerStatusForResultSets(packet); - + // // Handle cursor-based fetch first // - + if (this.connection.versionMeetsMinimum(5, 0, 2) && this.connection.getUseCursorFetch() && isBinaryEncoded && callingStatement != null && callingStatement.getFetchSize() != 0 && callingStatement.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) { ServerPreparedStatement prepStmt = (com.mysql.jdbc.ServerPreparedStatement) callingStatement; - - Field[] fieldMetadata = ((com.mysql.jdbc.ResultSetMetaData) prepStmt.getMetaData()).fields; boolean usingCursor = true; - + // // Server versions 5.0.5 or newer will only open // a cursor and set this flag if they can, otherwise // they punt and go back to mysql_store_results() behavior // - + if (this.connection.versionMeetsMinimum(5, 0, 5)) { - usingCursor = (this.serverStatus & + usingCursor = (this.serverStatus & SERVER_STATUS_CURSOR_EXISTS) != 0; } - + if (usingCursor) { - RowData rows = new CursorRowProvider( + RowData rows = new RowDataCursor( this, prepStmt, fields); - ResultSet rs = buildResultSetWithRows( + ResultSetImpl rs = buildResultSetWithRows( callingStatement, catalog, fields, rows, resultSetType, resultSetConcurrency, isBinaryEncoded); - + if (usingCursor) { rs.setFetchSize(callingStatement.getFetchSize()); } - + return rs; } } - + RowData rowData = null; - + if (!streamResults) { rowData = readSingleRowSet(columnCount, maxRows, - resultSetConcurrency, isBinaryEncoded, unpackFieldInfo ? fields : metadataFromCache); + resultSetConcurrency, isBinaryEncoded, + (metadataFromCache == null) ? fields : metadataFromCache); } else { - rowData = new RowDataDynamic(this, (int) columnCount, unpackFieldInfo ? fields : metadataFromCache, + rowData = new RowDataDynamic(this, (int) columnCount, + (metadataFromCache == null) ? fields : metadataFromCache, isBinaryEncoded); this.streamingData = rowData; } - ResultSet rs = buildResultSetWithRows(callingStatement, catalog, fields, + ResultSetImpl rs = buildResultSetWithRows(callingStatement, catalog, + (metadataFromCache == null) ? fields : metadataFromCache, rowData, resultSetType, resultSetConcurrency, isBinaryEncoded); - - - + + + return rs; } + // We do this to break the chain between MysqlIO and Connection, so that + // we can have PhantomReferences on connections that let the driver + // clean up the socket connection without having to use finalize() somewhere + // (which although more straightforward, is horribly inefficent). + protected NetworkResources getNetworkResources() { + return new NetworkResources(this.mysqlConnection, this.mysqlInput, this.mysqlOutput); + } + /** * Forcibly closes the underlying socket to MySQL. */ - protected final void forceClose() { + protected final void forceClose() { try { - if (this.mysqlInput != null) { - this.mysqlInput.close(); - } - } catch (IOException ioEx) { - // we can't do anything constructive about this - // Let the JVM clean it up later - this.mysqlInput = null; + getNetworkResources().forceClose(); + } finally { + this.mysqlConnection = null; + this.mysqlInput = null; + this.mysqlOutput = null; } - - try { - if (this.mysqlOutput != null) { - this.mysqlOutput.close(); - } - } catch (IOException ioEx) { - // we can't do anything constructive about this - // Let the JVM clean it up later - this.mysqlOutput = null; - } - - try { - if (this.mysqlConnection != null) { - this.mysqlConnection.close(); - } - } catch (IOException ioEx) { - // we can't do anything constructive about this - // Let the JVM clean it up later - this.mysqlConnection = null; - } } /** * Reads and discards a single MySQL packet from the input stream. - * - * @throws SQLException if the network fails while skipping the + * + * @throws SQLException if the network fails while skipping the * packet. */ protected final void skipPacket() throws SQLException { @@ -546,30 +573,28 @@ skipFully(this.mysqlInput, packetLength); } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } catch (OutOfMemoryError oom) { try { this.connection.realClose(false, false, true, oom); - } finally { - throw oom; - } + } catch (Exception ex) { + } + throw oom; } } - + /** - * Read one packet from the MySQL server - * - * @return the packet from the server. - * - * @throws SQLException - * DOCUMENT ME! - * @throws CommunicationsException - * DOCUMENT ME! - */ + * Read one packet from the MySQL server + * + * @return the packet from the server. + * + * @throws SQLException DOCUMENT ME! + * @throws CommunicationsException DOCUMENT ME! + */ protected final Buffer readPacket() throws SQLException { try { - + int lengthRead = readFully(this.mysqlInput, this.packetHeaderBuf, 0, 4); @@ -581,6 +606,10 @@ int packetLength = (this.packetHeaderBuf[0] & 0xff) + ((this.packetHeaderBuf[1] & 0xff) << 8) + ((this.packetHeaderBuf[2] & 0xff) << 16); + + if (packetLength > this.maxAllowedPacket) { + throw new PacketTooBigException(packetLength, this.maxAllowedPacket); + } if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); @@ -636,16 +665,20 @@ this.packetHeaderBuf, packet); } + if (this.connection.getMaintainTimeStats()) { + this.lastPacketReceivedTimeMs = System.currentTimeMillis(); + } + return packet; } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } catch (OutOfMemoryError oom) { try { this.connection.realClose(false, false, true, oom); - } finally { - throw oom; + } catch (Exception ex) { } + throw oom; } } @@ -679,7 +712,7 @@ int tableNameStart = packet.getPosition() + 1; int tableNameLength = packet.fastSkipLenString(); tableNameStart = adjustStartForFieldLength(tableNameStart, tableNameLength); - + // orgTableName is never used so skip int originalTableNameStart = packet.getPosition() + 1; int originalTableNameLength = packet.fastSkipLenString(); @@ -688,7 +721,7 @@ // we only store the position again... int nameStart = packet.getPosition() + 1; int nameLength = packet.fastSkipLenString(); - + nameStart = adjustStartForFieldLength(nameStart, nameLength); // orgColName is not required so skip... @@ -742,11 +775,11 @@ int tableNameStart = packet.getPosition() + 1; int tableNameLength = packet.fastSkipLenString(); tableNameStart = adjustStartForFieldLength(tableNameStart, tableNameLength); - + int nameStart = packet.getPosition() + 1; int nameLength = packet.fastSkipLenString(); nameStart = adjustStartForFieldLength(nameStart, nameLength); - + int colLength = packet.readnBytes(); int colType = packet.readnBytes(); packet.readByte(); // We know it's currently 2 @@ -776,15 +809,15 @@ if (nameLength < 251) { return nameStart; } - + if (nameLength >= 251 && nameLength < 65536) { return nameStart + 2; } - + if (nameLength >= 65536 && nameLength < 16777216) { return nameStart + 3; } - + return nameStart + 8; } @@ -808,7 +841,7 @@ return true; } - + protected boolean inTransactionOnServer() { return (this.serverStatus & SERVER_STATUS_IN_TRANS) != 0; } @@ -825,14 +858,19 @@ protected void changeUser(String userName, String password, String database) throws SQLException { this.packetSequence = -1; + this.compressedPacketSequence = -1; int passwordLength = 16; int userLength = (userName != null) ? userName.length() : 0; int databaseLength = (database != null) ? database.length() : 0; - - int packLength = ((userLength + passwordLength + databaseLength) * 2) + 7 + HEADER_LENGTH + AUTH_411_OVERHEAD; - if ((this.serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) { + int packLength = ((userLength + passwordLength + databaseLength) * 3) + 7 + HEADER_LENGTH + AUTH_411_OVERHEAD; + + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH) != 0) { + + proceedHandshakeWithPluggableAuthentication(userName, password, database, null); + + } else if ((this.serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) { Buffer changeUserPacket = new Buffer(packLength + 1); changeUserPacket.writeByte((byte) MysqlDefs.COM_CHANGE_USER); @@ -857,16 +895,19 @@ packet.writeString(Util.oldCrypt(password, this.seed)); } - boolean localUseConnectWithDb = this.useConnectWithDb && + boolean localUseConnectWithDb = this.useConnectWithDb && (database != null && database.length() > 0); - + if (localUseConnectWithDb) { packet.writeString(database); + } else { + //Not needed, old server does not require \0 + //packet.writeString(""); } send(packet, packet.getPosition()); checkErrorPacket(); - + if (!localUseConnectWithDb) { changeDatabaseTo(database); } @@ -906,7 +947,7 @@ } protected void clearInputStream() throws SQLException { - + try { int len = this.mysqlInput.available(); @@ -915,8 +956,8 @@ len = this.mysqlInput.available(); } } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } } @@ -933,9 +974,9 @@ " packets received from server, from oldest->newest:\n"); dumpBuffer.append("\n"); - for (Iterator ringBufIter = this.packetDebugRingBuffer.iterator(); + for (Iterator ringBufIter = this.packetDebugRingBuffer.iterator(); ringBufIter.hasNext();) { - dumpBuffer.append((StringBuffer) ringBufIter.next()); + dumpBuffer.append(ringBufIter.next()); dumpBuffer.append("\n"); } @@ -953,13 +994,15 @@ */ protected void explainSlowQuery(byte[] querySQL, String truncatedQuery) throws SQLException { - if (StringUtils.startsWithIgnoreCaseAndWs(truncatedQuery, "SELECT")) { //$NON-NLS-1$ + if (StringUtils.startsWithIgnoreCaseAndWs(truncatedQuery, EXPLAINABLE_STATEMENT) + || (versionMeetsMinimum(5, 6, 3) && StringUtils.startsWithIgnoreCaseAndWs(truncatedQuery, + EXPLAINABLE_STATEMENT_EXTENSION) != -1)) { PreparedStatement stmt = null; java.sql.ResultSet rs = null; try { - stmt = this.connection.clientPrepareStatement("EXPLAIN ?"); //$NON-NLS-1$ + stmt = (PreparedStatement) this.connection.clientPrepareStatement("EXPLAIN ?"); //$NON-NLS-1$ stmt.setBytesNoEscapeNoQuotes(1, querySQL); rs = stmt.executeQuery(); @@ -980,7 +1023,6 @@ stmt.close(); } } - } else { } } @@ -1050,14 +1092,14 @@ try { this.mysqlConnection.close(); } catch (Exception e) { - ; // ignore + // ignore } int errno = 2000; errno = buf.readInt(); - String serverErrorMessage = buf.readString(); + String serverErrorMessage = buf.readString("ASCII", getExceptionInterceptor()); StringBuffer errorBuf = new StringBuffer(Messages.getString( "MysqlIO.10")); //$NON-NLS-1$ @@ -1068,32 +1110,32 @@ this.connection.getUseSqlStateCodes()); throw SQLError.createSQLException(SQLError.get(xOpen) + ", " //$NON-NLS-1$ - +errorBuf.toString(), xOpen, errno); + +errorBuf.toString(), xOpen, errno, getExceptionInterceptor()); } - this.serverVersion = buf.readString(); + this.serverVersion = buf.readString("ASCII", getExceptionInterceptor()); // Parse the server version into major/minor/subminor - int point = this.serverVersion.indexOf("."); //$NON-NLS-1$ + int point = this.serverVersion.indexOf('.'); //$NON-NLS-1$ if (point != -1) { try { int n = Integer.parseInt(this.serverVersion.substring(0, point)); this.serverMajorVersion = n; } catch (NumberFormatException NFE1) { - ; + // ignore } String remaining = this.serverVersion.substring(point + 1, this.serverVersion.length()); - point = remaining.indexOf("."); //$NON-NLS-1$ + point = remaining.indexOf('.'); //$NON-NLS-1$ if (point != -1) { try { int n = Integer.parseInt(remaining.substring(0, point)); this.serverMinorVersion = n; } catch (NumberFormatException nfe) { - ; + // ignore } remaining = remaining.substring(point + 1, remaining.length()); @@ -1113,7 +1155,7 @@ int n = Integer.parseInt(remaining.substring(0, pos)); this.serverSubMinorVersion = n; } catch (NumberFormatException nfe) { - ; + // ignore } } } @@ -1129,40 +1171,81 @@ this.colDecimalNeedsBump = versionMeetsMinimum(3, 23, 0); this.colDecimalNeedsBump = !versionMeetsMinimum(3, 23, 15); // guess? Not noted in changelog this.useNewUpdateCounts = versionMeetsMinimum(3, 22, 5); + + // read connection id + threadId = buf.readLong(); + + if (this.protocolVersion > 9) { + // read auth-plugin-data-part-1 (string[8]) + this.seed = buf.readString("ASCII", getExceptionInterceptor(), 8); + // read filler ([00]) + buf.readByte(); + } else { + // read scramble (string[NUL]) + this.seed = buf.readString("ASCII", getExceptionInterceptor()); + } - threadId = buf.readLong(); - this.seed = buf.readString(); - this.serverCapabilities = 0; + // read capability flags (lower 2 bytes) if (buf.getPosition() < buf.getBufLength()) { this.serverCapabilities = buf.readInt(); } - if (versionMeetsMinimum(4, 1, 1)) { - int position = buf.getPosition(); + if ((versionMeetsMinimum(4, 1, 1) || ((this.protocolVersion > 9) && (this.serverCapabilities & CLIENT_PROTOCOL_41) != 0))) { /* New protocol with 16 bytes to describe server characteristics */ + // read character set (1 byte) this.serverCharsetIndex = buf.readByte() & 0xff; + // read status flags (2 bytes) this.serverStatus = buf.readInt(); - buf.setPosition(position + 16); + checkTransactionState(0); + + // read capability flags (upper 2 bytes) + this.serverCapabilities |= buf.readInt() << 16; + + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH) != 0) { + // read length of auth-plugin-data (1 byte) + this.authPluginDataLength = buf.readByte() & 0xff; + } else { + // read filler ([00]) + buf.readByte(); + } + // next 10 bytes are reserved (all [00]) + buf.setPosition(buf.getPosition() + 10); - String seedPart2 = buf.readString(); - StringBuffer newSeed = new StringBuffer(20); - newSeed.append(this.seed); - newSeed.append(seedPart2); - this.seed = newSeed.toString(); + if ((this.serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) { + String seedPart2; + StringBuffer newSeed; + // read string[$len] auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8)) + if (this.authPluginDataLength > 0) { +// TODO: disabled the following check for further clarification +// if (this.authPluginDataLength < 21) { +// forceClose(); +// throw SQLError.createSQLException(Messages.getString("MysqlIO.103"), //$NON-NLS-1$ +// SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, getExceptionInterceptor()); +// } + seedPart2 = buf.readString("ASCII", getExceptionInterceptor(), this.authPluginDataLength - 8); + newSeed = new StringBuffer(this.authPluginDataLength); + } else { + seedPart2 = buf.readString("ASCII", getExceptionInterceptor()); + newSeed = new StringBuffer(20); + } + newSeed.append(this.seed); + newSeed.append(seedPart2); + this.seed = newSeed.toString(); + } } if (((this.serverCapabilities & CLIENT_COMPRESS) != 0) && this.connection.getUseCompression()) { this.clientParam |= CLIENT_COMPRESS; } - this.useConnectWithDb = (database != null) && + this.useConnectWithDb = (database != null) && (database.length() > 0) && !this.connection.getCreateDatabaseIfNotExist(); - + if (this.useConnectWithDb) { this.clientParam |= CLIENT_CONNECT_WITH_DB; } @@ -1173,7 +1256,7 @@ this.connection.close(); forceClose(); throw SQLError.createSQLException(Messages.getString("MysqlIO.15"), //$NON-NLS-1$ - SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, getExceptionInterceptor()); } this.connection.setUseSSL(false); @@ -1186,7 +1269,9 @@ } // return FOUND rows - this.clientParam |= CLIENT_FOUND_ROWS; + if (!this.connection.getUseAffectedRows()) { + this.clientParam |= CLIENT_FOUND_ROWS; + } if (this.connection.getAllowLoadLocalInfile()) { this.clientParam |= CLIENT_LOCAL_FILES; @@ -1196,6 +1281,14 @@ this.clientParam |= CLIENT_INTERACTIVE; } + // + // switch to pluggable authentication if available + // + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH) != 0) { + proceedHandshakeWithPluggableAuthentication(user, password, database, buf); + return; + } + // Authenticate if (this.protocolVersion > 9) { this.clientParam |= CLIENT_LONG_PASSWORD; // for long passwords @@ -1206,8 +1299,8 @@ // // 4.1 has some differences in the protocol // - if (versionMeetsMinimum(4, 1, 0)) { - if (versionMeetsMinimum(4, 1, 1)) { + if ((versionMeetsMinimum(4, 1, 0) || ((this.protocolVersion > 9) && (this.serverCapabilities & CLIENT_RESERVED) != 0))) { + if ((versionMeetsMinimum(4, 1, 1) || ((this.protocolVersion > 9) && (this.serverCapabilities & CLIENT_PROTOCOL_41) != 0))) { this.clientParam |= CLIENT_PROTOCOL_41; this.has41NewNewProt = true; @@ -1221,7 +1314,7 @@ // or not they want to support multiple queries // (by default, this is disabled). if (this.connection.getAllowMultiQueries()) { - this.clientParam |= CLIENT_MULTI_QUERIES; + this.clientParam |= CLIENT_MULTI_STATEMENTS; } } else { this.clientParam |= CLIENT_RESERVED; @@ -1234,16 +1327,16 @@ int passwordLength = 16; int userLength = (user != null) ? user.length() : 0; int databaseLength = (database != null) ? database.length() : 0; - - int packLength = ((userLength + passwordLength + databaseLength) * 2) + 7 + HEADER_LENGTH + AUTH_411_OVERHEAD; - + + int packLength = ((userLength + passwordLength + databaseLength) * 3) + 7 + HEADER_LENGTH + AUTH_411_OVERHEAD; + Buffer packet = null; if (!this.connection.getUseSSL()) { if ((this.serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) { this.clientParam |= CLIENT_SECURE_CONNECTION; - if (versionMeetsMinimum(4, 1, 1)) { + if ((versionMeetsMinimum(4, 1, 1) || ((this.protocolVersion > 9) && (this.serverCapabilities & CLIENT_PROTOCOL_41) != 0))) { secureAuth411(null, packLength, user, password, database, true); } else { @@ -1254,7 +1347,7 @@ packet = new Buffer(packLength); if ((this.clientParam & CLIENT_RESERVED) != 0) { - if (versionMeetsMinimum(4, 1, 1)) { + if ((versionMeetsMinimum(4, 1, 1) || ((this.protocolVersion > 9) && (this.serverCapabilities & CLIENT_PROTOCOL_41) != 0))) { packet.writeLong(this.clientParam); packet.writeLong(this.maxThreeBytes); @@ -1275,28 +1368,64 @@ } // User/Password data - packet.writeString(user, "Cp1252", this.connection); + packet.writeString(user, CODE_PAGE_1252, this.connection); if (this.protocolVersion > 9) { - packet.writeString(Util.newCrypt(password, this.seed), "Cp1252", this.connection); + packet.writeString(Util.newCrypt(password, this.seed), CODE_PAGE_1252, this.connection); } else { - packet.writeString(Util.oldCrypt(password, this.seed), "Cp1252", this.connection); + packet.writeString(Util.oldCrypt(password, this.seed), CODE_PAGE_1252, this.connection); } if (this.useConnectWithDb) { - packet.writeString(database, "Cp1252", this.connection); + packet.writeString(database, CODE_PAGE_1252, this.connection); } send(packet, packet.getPosition()); } } else { negotiateSSLConnection(user, password, database, packLength); + + if ((this.serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) { + if (versionMeetsMinimum(4, 1, 1)) { + secureAuth411(null, packLength, user, password, database, true); + } else { + secureAuth411(null, packLength, user, password, database, true); + } + } else { + + packet = new Buffer(packLength); + + if (this.use41Extensions) { + packet.writeLong(this.clientParam); + packet.writeLong(this.maxThreeBytes); + } else { + packet.writeInt((int) this.clientParam); + packet.writeLongInt(this.maxThreeBytes); + } + + // User/Password data + packet.writeString(user); + + if (this.protocolVersion > 9) { + packet.writeString(Util.newCrypt(password, this.seed)); + } else { + packet.writeString(Util.oldCrypt(password, this.seed)); + } + + if (((this.serverCapabilities & CLIENT_CONNECT_WITH_DB) != 0) && + (database != null) && (database.length() > 0)) { + packet.writeString(database); + } + + send(packet, packet.getPosition()); + } } // Check for errors, not for 4.1.1 or newer, // as the new auth protocol doesn't work that way // (see secureAuth411() for more details...) - if (!versionMeetsMinimum(4, 1, 1)) { + //if (!versionMeetsMinimum(4, 1, 1)) { + if (!(versionMeetsMinimum(4, 1, 1) || !((this.protocolVersion > 9) && (this.serverCapabilities & CLIENT_PROTOCOL_41) != 0))) { checkErrorPacket(); } @@ -1316,24 +1445,573 @@ if (!this.useConnectWithDb) { changeDatabaseTo(database); } + + try { + this.mysqlConnection = this.socketFactory.afterHandshake(); + } catch (IOException ioEx) { + throw SQLError.createCommunicationsException(this.connection, this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); + } } - private void changeDatabaseTo(String database) throws SQLException, CommunicationsException { + + /** + * Contains instances of authentication plugins which implements + * {@link AuthenticationPlugin} interface. Key values are mysql + * protocol plugin names, for example "mysql_native_password" and + * "mysql_old_password" for built-in plugins. + */ + private Map authenticationPlugins = null; + /** + * Contains names of classes or mechanisms ("mysql_native_password" + * for example) of authentication plugins which must be disabled. + */ + private List disabledAuthenticationPlugins = null; + /** + * Name of class for default authentication plugin + */ + private String defaultAuthenticationPlugin = null; + /** + * Protocol name of default authentication plugin + */ + private String defaultAuthenticationPluginProtocolName = null; + + /** + * Fill the {@link MysqlIO#authenticationPlugins} map. + * First this method fill the map with instances of {@link MysqlOldPasswordPlugin}, {@link MysqlNativePasswordPlugin}, + * {@link MysqlClearPasswordPlugin} and {@link Sha256PasswordPlugin}. + * Then it gets instances of plugins listed in "authenticationPlugins" connection property by + * {@link Util#loadExtensions(Connection, Properties, String, String, ExceptionInterceptor)} call and adds them to the map too. + * + * The key for the map entry is getted by {@link AuthenticationPlugin#getProtocolPluginName()}. + * Thus it is possible to replace built-in plugin with custom one, to do it custom plugin should return value + * "mysql_native_password", "mysql_old_password", "mysql_clear_password" or "sha256_password" from it's own getProtocolPluginName() method. + * + * All plugin instances in the map are initialized by {@link Extension#init(Connection, Properties)} call + * with this.connection and this.connection.getProperties() values. + * + * @throws SQLException + */ + private void loadAuthenticationPlugins() throws SQLException { + + // default plugin + this.defaultAuthenticationPlugin = this.connection.getDefaultAuthenticationPlugin(); + if (this.defaultAuthenticationPlugin == null || "".equals(defaultAuthenticationPlugin.trim())) { + throw SQLError.createSQLException( + Messages.getString("Connection.BadDefaultAuthenticationPlugin", + new Object[] { this.defaultAuthenticationPlugin }), + getExceptionInterceptor()); + } + + // disabled plugins + String disabledPlugins = this.connection.getDisabledAuthenticationPlugins(); + if (disabledPlugins != null && !"".equals(disabledPlugins)) { + this.disabledAuthenticationPlugins = new ArrayList(); + List pluginsToDisable = StringUtils.split(disabledPlugins, ",", true); + Iterator iter = pluginsToDisable.iterator(); + while (iter.hasNext()) { + this.disabledAuthenticationPlugins.add(iter.next()); + } + } + + this.authenticationPlugins = new HashMap(); + + // embedded plugins + AuthenticationPlugin plugin = new MysqlOldPasswordPlugin(); + plugin.init(this.connection, this.connection.getProperties()); + boolean defaultIsFound = addAuthenticationPlugin(plugin); + + plugin = new MysqlNativePasswordPlugin(); + plugin.init(this.connection, this.connection.getProperties()); + if (addAuthenticationPlugin(plugin)) defaultIsFound = true; + + plugin = new MysqlClearPasswordPlugin(); + plugin.init(this.connection, this.connection.getProperties()); + if (addAuthenticationPlugin(plugin)) defaultIsFound = true; + + plugin = new Sha256PasswordPlugin(); + plugin.init(this.connection, this.connection.getProperties()); + if (addAuthenticationPlugin(plugin)) defaultIsFound = true; + + // plugins from authenticationPluginClasses connection parameter + String authenticationPluginClasses = this.connection.getAuthenticationPlugins(); + if (authenticationPluginClasses != null && !"".equals(authenticationPluginClasses)) { + + List plugins = Util.loadExtensions( + this.connection, this.connection.getProperties(), authenticationPluginClasses, + "Connection.BadAuthenticationPlugin", getExceptionInterceptor()); + + for (Extension object : plugins) { + plugin = (AuthenticationPlugin) object; + if (addAuthenticationPlugin(plugin)) defaultIsFound = true; + } + } + + // check if default plugin is listed + if (!defaultIsFound) { + throw SQLError.createSQLException( + Messages.getString("Connection.DefaultAuthenticationPluginIsNotListed", + new Object[] { this.defaultAuthenticationPlugin }), + getExceptionInterceptor()); + } + + } + + /** + * Add plugin to {@link MysqlIO#authenticationPlugins} if it is not disabled by + * "disabledAuthenticationPlugins" property, check is it a default plugin. + * @param plugin Instance of AuthenticationPlugin + * @return True if plugin is default, false if plugin is not default. + * @throws SQLException if plugin is default but disabled. + */ + private boolean addAuthenticationPlugin(AuthenticationPlugin plugin) throws SQLException { + boolean isDefault = false; + String pluginClassName = plugin.getClass().getName(); + String pluginProtocolName = plugin.getProtocolPluginName(); + boolean disabledByClassName = + this.disabledAuthenticationPlugins != null && + this.disabledAuthenticationPlugins.contains(pluginClassName); + boolean disabledByMechanism = + this.disabledAuthenticationPlugins != null && + this.disabledAuthenticationPlugins.contains(pluginProtocolName); + + if (disabledByClassName || disabledByMechanism) { + // if disabled then check is it default + if (this.defaultAuthenticationPlugin.equals(pluginClassName)) { + throw SQLError.createSQLException( + Messages.getString("Connection.BadDisabledAuthenticationPlugin", + new Object[] { disabledByClassName ? pluginClassName : pluginProtocolName}), + getExceptionInterceptor()); + } + } else { + this.authenticationPlugins.put(pluginProtocolName , plugin); + if (this.defaultAuthenticationPlugin.equals(pluginClassName)) { + this.defaultAuthenticationPluginProtocolName = pluginProtocolName; + isDefault = true; + } + } + return isDefault; + } + + /** + * Get authentication plugin instance from {@link MysqlIO#authenticationPlugins} map by + * pluginName key. If such plugin is found it's {@link AuthenticationPlugin#isReusable()} method + * is checked, when it's false this method returns a new instance of plugin + * and the same instance otherwise. + * + * If plugin is not found method returns null, in such case the subsequent behavior + * of handshake process depends on type of last packet received from server: + * if it was Auth Challenge Packet then handshake will proceed with default plugin, + * if it was Auth Method Switch Request Packet then handshake will be interrupted with exception. + * + * @param pluginName mysql protocol plugin names, for example "mysql_native_password" and "mysql_old_password" for built-in plugins + * @return null if plugin is not found or authentication plugin instance initialized with current connection properties + * @throws SQLException + */ + private AuthenticationPlugin getAuthenticationPlugin(String pluginName) throws SQLException { + + AuthenticationPlugin plugin = this.authenticationPlugins.get(pluginName); + + if (plugin != null && !plugin.isReusable()) { + try { + plugin = plugin.getClass().newInstance(); + plugin.init(this.connection, this.connection.getProperties()); + } catch (Throwable t) { + SQLException sqlEx = SQLError.createSQLException(Messages + .getString("Connection.BadAuthenticationPlugin", new Object[] { plugin.getClass().getName() }), getExceptionInterceptor()); + sqlEx.initCause(t); + throw sqlEx; + } + } + + return plugin; + } + + /** + * Check if given plugin requires confidentiality, but connection is without SSL + * @param plugin + * @throws SQLException + */ + private void checkConfidentiality(AuthenticationPlugin plugin) throws SQLException { + if (plugin.requiresConfidentiality() && !isSSLEstablished()) { + throw SQLError.createSQLException( + Messages.getString("Connection.AuthenticationPluginRequiresSSL", new Object[] {plugin.getProtocolPluginName()}), getExceptionInterceptor()); + } + } + + /** + * Performs an authentication handshake to authorize connection to a + * given database as a given MySQL user. This can happen upon initial + * connection to the server, after receiving Auth Challenge Packet, or + * at any moment during the connection life-time via a Change User + * request. + * + * This method is aware of pluggable authentication and will use + * registered authentication plugins as requested by the server. + * + * @param user the MySQL user account to log into + * @param password authentication data for the user account (depends + * on authentication method used - can be empty) + * @param database database to connect to (can be empty) + * @param challenge the Auth Challenge Packet received from server if + * this method is used during the initial connection. + * Otherwise null. + * + * @throws SQLException + */ + private void proceedHandshakeWithPluggableAuthentication(String user, String password, String database, Buffer challenge) throws SQLException { + if (this.authenticationPlugins == null) { + loadAuthenticationPlugins(); + } + + int passwordLength = 16; + int userLength = (user != null) ? user.length() : 0; + int databaseLength = (database != null) ? database.length() : 0; + + int packLength = ((userLength + passwordLength + databaseLength) * 3) + 7 + HEADER_LENGTH + AUTH_411_OVERHEAD; + + AuthenticationPlugin plugin = null; + Buffer fromServer = null; + ArrayList toServer = new ArrayList(); + Boolean done = null; + Buffer last_sent = null; + + boolean old_raw_challenge = false; + + int counter = 100; + + while (0 < counter--) { + + if (done == null) { + + if (challenge != null) { + // read Auth Challenge Packet + + this.clientParam |= + CLIENT_PLUGIN_AUTH + | CLIENT_LONG_PASSWORD + | CLIENT_PROTOCOL_41 + | CLIENT_TRANSACTIONS // Need this to get server status values + | CLIENT_MULTI_RESULTS // We always allow multiple result sets + | CLIENT_SECURE_CONNECTION // protocol with pluggable authentication always support this + ; + + // We allow the user to configure whether + // or not they want to support multiple queries + // (by default, this is disabled). + if (this.connection.getAllowMultiQueries()) { + this.clientParam |= CLIENT_MULTI_STATEMENTS; + } + + if (((this.serverCapabilities & CLIENT_CAN_HANDLE_EXPIRED_PASSWORD) != 0) && !this.connection.getDisconnectOnExpiredPasswords()) { + this.clientParam |= CLIENT_CAN_HANDLE_EXPIRED_PASSWORD; + } + if (((this.serverCapabilities & CLIENT_CONNECT_ATTRS) != 0 ) && + !NONE.equals(this.connection.getConnectionAttributes())) { + this.clientParam |= CLIENT_CONNECT_ATTRS; + } + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) != 0 ) { + this.clientParam |= CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA; + } + + this.has41NewNewProt = true; + this.use41Extensions = true; + + if (this.connection.getUseSSL()) { + negotiateSSLConnection(user, password, database, packLength); + } + + String pluginName = null; + // Due to Bug#59453 the auth-plugin-name is missing the terminating NUL-char in versions prior to 5.5.10 and 5.6.2. + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH) != 0) { + if (!versionMeetsMinimum(5, 5, 10) || versionMeetsMinimum(5, 6, 0) && !versionMeetsMinimum(5, 6, 2)) { + pluginName = challenge.readString("ASCII", getExceptionInterceptor(), this.authPluginDataLength); + } else { + pluginName = challenge.readString("ASCII", getExceptionInterceptor()); + } + } + + plugin = getAuthenticationPlugin(pluginName); + // if plugin is not found for pluginName get default instead + if (plugin == null) plugin = getAuthenticationPlugin(this.defaultAuthenticationPluginProtocolName); + + checkConfidentiality(plugin); + fromServer = new Buffer(StringUtils.getBytes(this.seed)); + } else { + // no challenge so this is a changeUser call + plugin = getAuthenticationPlugin(this.defaultAuthenticationPluginProtocolName); + checkConfidentiality(plugin); + } + + } else { + + // read packet from server and check if it's an ERROR packet + challenge = checkErrorPacket(); + old_raw_challenge = false; + + if (challenge.isOKPacket()) { + // if OK packet then finish handshake + if (!done) { + throw SQLError.createSQLException(Messages.getString("Connection.UnexpectedAuthenticationApproval", new Object[] {plugin.getProtocolPluginName()}), getExceptionInterceptor()); + } + plugin.destroy(); + break; + + } else if (challenge.isAuthMethodSwitchRequestPacket()) { + // read Auth Method Switch Request Packet + String pluginName = challenge.readString("ASCII", getExceptionInterceptor()); + + // get new plugin + if (plugin != null && !plugin.getProtocolPluginName().equals(pluginName)) { + plugin.destroy(); + plugin = getAuthenticationPlugin(pluginName); + // if plugin is not found for pluginName throw exception + if (plugin == null) { + throw SQLError.createSQLException(Messages.getString("Connection.BadAuthenticationPlugin", new Object[] {pluginName}), getExceptionInterceptor()); + } + } + + checkConfidentiality(plugin); + fromServer = new Buffer(StringUtils.getBytes(challenge.readString("ASCII", getExceptionInterceptor()))); + + } else { + // read raw packet + if (versionMeetsMinimum(5, 5, 16)) { + fromServer = new Buffer(challenge.getBytes(challenge.getPosition(), challenge.getBufLength()-challenge.getPosition())); + } else { + old_raw_challenge = true; + fromServer = new Buffer(challenge.getBytes(challenge.getPosition()-1, challenge.getBufLength()-challenge.getPosition()+1)); + } + } + + } + + // call plugin + try { + plugin.setAuthenticationParameters(user, password); + done = plugin.nextAuthenticationStep(fromServer, toServer); + } catch (SQLException e) { + throw SQLError.createSQLException(e.getMessage(), e.getSQLState(), e, getExceptionInterceptor()); + } + + // send response + if (toServer.size() > 0) { + if (challenge == null) { + // write COM_CHANGE_USER Packet + + String enc = this.connection.getEncoding(); + int charsetIndex = 0; + if (enc != null) { + charsetIndex = CharsetMapping.getCharsetIndexForMysqlEncodingName(CharsetMapping.getMysqlEncodingForJavaEncoding(enc, this.connection)); + } else { + enc = "utf-8"; + } + if (charsetIndex == 0) { + charsetIndex = UTF8_CHARSET_INDEX; + } + + + last_sent = new Buffer(packLength + 1); + last_sent.writeByte((byte) MysqlDefs.COM_CHANGE_USER); + + // User/Password data + last_sent.writeString(user, enc, this.connection); + + last_sent.writeByte((byte) toServer.get(0).getBufLength()); + last_sent.writeBytesNoNull(toServer.get(0).getByteBuffer(), 0, toServer.get(0).getBufLength()); + + if (this.useConnectWithDb) { + last_sent.writeString(database, enc, this.connection); + } else { + /* For empty database*/ + last_sent.writeByte((byte) 0); + } + + // charset (2 bytes low-endian) + last_sent.writeByte((byte) (charsetIndex % 256)); + if (charsetIndex > 255) { + last_sent.writeByte((byte) (charsetIndex / 256)); + } else { + last_sent.writeByte((byte) 0); + } + + // plugin name + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH) != 0) { + last_sent.writeString(plugin.getProtocolPluginName(), enc, this.connection); + } + + // connection attributes + if ((this.clientParam & CLIENT_CONNECT_ATTRS) != 0) { + sendConnectionAttributes(last_sent, enc, this.connection); + last_sent.writeByte((byte) 0); + } + + send(last_sent, last_sent.getPosition()); + + } else if (challenge.isAuthMethodSwitchRequestPacket()) { + // write Auth Method Switch Response Packet + + byte savePacketSequence = this.packetSequence++; + this.packetSequence = ++savePacketSequence; + + last_sent = new Buffer(toServer.get(0).getBufLength()+HEADER_LENGTH); + last_sent.writeBytesNoNull(toServer.get(0).getByteBuffer(), 0, toServer.get(0).getBufLength()); + send(last_sent, last_sent.getPosition()); + + } else if (challenge.isRawPacket() || old_raw_challenge) { + // write raw packet(s) + byte savePacketSequence = this.packetSequence++; + + for (Buffer buffer : toServer) { + this.packetSequence = ++savePacketSequence; + + last_sent = new Buffer(buffer.getBufLength()+HEADER_LENGTH); + last_sent.writeBytesNoNull(buffer.getByteBuffer(), 0, toServer.get(0).getBufLength()); + send(last_sent, last_sent.getPosition()); + } + + } else { + // write Auth Response Packet + + last_sent = new Buffer(packLength); + last_sent.writeLong(this.clientParam); + last_sent.writeLong(this.maxThreeBytes); + + // charset, JDBC will connect as 'utf8', + // and use 'SET NAMES' to change to the desired + // charset after the connection is established. + last_sent.writeByte((byte) UTF8_CHARSET_INDEX); + + last_sent.writeBytesNoNull(new byte[23]); // Set of bytes reserved for future use. + + // User/Password data + last_sent.writeString(user, "utf-8", this.connection); + + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) != 0 ) { + // send lenenc-int length of auth-response and string[n] auth-response + last_sent.writeLenBytes(toServer.get(0).getBytes(toServer.get(0).getBufLength())); + } else { + // send 1 byte length of auth-response and string[n] auth-response + last_sent.writeByte((byte) toServer.get(0).getBufLength()); + last_sent.writeBytesNoNull(toServer.get(0).getByteBuffer(), 0, toServer.get(0).getBufLength()); + } + + if (this.useConnectWithDb) { + last_sent.writeString(database, "utf-8", this.connection); + } else { + /* For empty database*/ + last_sent.writeByte((byte) 0); + } + + if ((this.serverCapabilities & CLIENT_PLUGIN_AUTH) != 0) { + last_sent.writeString(plugin.getProtocolPluginName(), "utf-8", this.connection); + } + + // connection attributes + if (((this.clientParam & CLIENT_CONNECT_ATTRS) != 0) ) { + sendConnectionAttributes(last_sent, "utf-8", this.connection); + } + + send(last_sent, last_sent.getPosition()); + } + + } + + } + + if (counter == 0) { + throw SQLError.createSQLException(Messages.getString("CommunicationsException.TooManyAuthenticationPluginNegotiations"), getExceptionInterceptor()); + } + + // + // Can't enable compression until after handshake + // + if (((this.serverCapabilities & CLIENT_COMPRESS) != 0) && + this.connection.getUseCompression()) { + // The following matches with ZLIB's + // compress() + this.deflater = new Deflater(); + this.useCompression = true; + this.mysqlInput = new CompressedInputStream(this.connection, this.mysqlInput); + } + + if (!this.useConnectWithDb) { + changeDatabaseTo(database); + } + + try { + this.mysqlConnection = this.socketFactory.afterHandshake(); + } catch (IOException ioEx) { + throw SQLError.createCommunicationsException(this.connection, this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); + } + } + + private Properties getConnectionAttributesAsProperties(String atts) throws SQLException { + + Properties props = new Properties(); + + + if(atts != null) { + String[] pairs = atts.split(","); + for(String pair : pairs){ + int keyEnd = pair.indexOf(":"); + if (keyEnd > 0 && (keyEnd + 1) < pair.length()) { + props.setProperty(pair.substring(0,keyEnd), pair.substring(keyEnd + 1)); + } + } + } + +// Leaving disabled until standard values are defined +// props.setProperty("_os", NonRegisteringDriver.OS); +// props.setProperty("_platform", NonRegisteringDriver.PLATFORM); + props.setProperty("_client_name", NonRegisteringDriver.NAME); + props.setProperty("_client_version", NonRegisteringDriver.VERSION); + props.setProperty("_runtime_vendor", NonRegisteringDriver.RUNTIME_VENDOR); + props.setProperty("_runtime_version", NonRegisteringDriver.RUNTIME_VERSION); + props.setProperty("_client_license", NonRegisteringDriver.LICENSE); + + + return props; + } + + private void sendConnectionAttributes(Buffer buf, String enc, MySQLConnection conn) throws SQLException { + String atts = conn.getConnectionAttributes(); + + Buffer lb = new Buffer(100); + try{ + + Properties props = getConnectionAttributesAsProperties(atts); + + for(Object key : props.keySet()) { + lb.writeLenString((String) key, enc, conn.getServerCharacterEncoding(), null, conn.parserKnowsUnicode(), conn); + lb.writeLenString(props.getProperty((String) key), enc, conn.getServerCharacterEncoding(), null, conn.parserKnowsUnicode(), conn); + } + + } catch (UnsupportedEncodingException e){ + + } + + buf.writeByte((byte) (lb.getPosition() - 4)); + buf.writeBytesNoNull(lb.getByteBuffer(), 4 , lb.getBufLength() - 4); + + } + + + private void changeDatabaseTo(String database) throws SQLException { if (database == null || database.length() == 0) { return; } - + try { - sendCommand(MysqlDefs.INIT_DB, database, null, false, null); + sendCommand(MysqlDefs.INIT_DB, database, null, false, null, 0); } catch (Exception ex) { if (this.connection.getCreateDatabaseIfNotExist()) { sendCommand(MysqlDefs.QUERY, "CREATE DATABASE IF NOT EXISTS " + database, - null, false, null); - sendCommand(MysqlDefs.INIT_DB, database, null, false, null); + null, false, null, 0); + sendCommand(MysqlDefs.INIT_DB, database, null, false, null, 0); } else { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ex); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ex, getExceptionInterceptor()); } } } @@ -1347,18 +2025,44 @@ * @param columnCount DOCUMENT ME! * @param isBinaryEncoded DOCUMENT ME! * @param resultSetConcurrency DOCUMENT ME! + * @param b * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ - final Object[] nextRow(Field[] fields, int columnCount, - boolean isBinaryEncoded, int resultSetConcurrency) + final ResultSetRow nextRow(Field[] fields, int columnCount, + boolean isBinaryEncoded, int resultSetConcurrency, + boolean useBufferRowIfPossible, + boolean useBufferRowExplicit, + boolean canReuseRowPacketForBufferRow, Buffer existingRowPacket) throws SQLException { - // Get the next incoming packet, re-using the packet because - // all the data we need gets copied out of it. - Buffer rowPacket = checkErrorPacket(); + if (this.useDirectRowUnpack && existingRowPacket == null + && !isBinaryEncoded && !useBufferRowIfPossible + && !useBufferRowExplicit) { + return nextRowFast(fields, columnCount, isBinaryEncoded, resultSetConcurrency, + useBufferRowIfPossible, useBufferRowExplicit, canReuseRowPacketForBufferRow); + } + + Buffer rowPacket = null; + + if (existingRowPacket == null) { + rowPacket = checkErrorPacket(); + + if (!useBufferRowExplicit && useBufferRowIfPossible) { + if (rowPacket.getBufLength() > this.useBufferRowSizeThreshold) { + useBufferRowExplicit = true; + } + } + } else { + // We attempted to do nextRowFast(), but the packet was a + // multipacket, so we couldn't unpack it directly + rowPacket = existingRowPacket; + checkErrorPacket(existingRowPacket); + } + + if (!isBinaryEncoded) { // // Didn't read an error, so re-position to beginning @@ -1367,29 +2071,47 @@ rowPacket.setPosition(rowPacket.getPosition() - 1); if (!rowPacket.isLastDataPacket()) { - byte[][] rowData = new byte[columnCount][]; + if (resultSetConcurrency == ResultSet.CONCUR_UPDATABLE + || (!useBufferRowIfPossible && !useBufferRowExplicit)) { - int offset = 0; + byte[][] rowData = new byte[columnCount][]; - for (int i = 0; i < columnCount; i++) { - rowData[i] = rowPacket.readLenByteArray(offset); - } + for (int i = 0; i < columnCount; i++) { + rowData[i] = rowPacket.readLenByteArray(0); + } - return rowData; + return new ByteArrayRow(rowData, getExceptionInterceptor()); + } + + if (!canReuseRowPacketForBufferRow) { + this.reusablePacket = new Buffer(rowPacket.getBufLength()); + } + + return new BufferRow(rowPacket, fields, false, getExceptionInterceptor()); + } readServerStatusForResultSets(rowPacket); return null; } - // - // Handle binary-encoded data for server-side + // + // Handle binary-encoded data for server-side // PreparedStatements... // if (!rowPacket.isLastDataPacket()) { - return unpackBinaryResultSetRow(fields, rowPacket, - resultSetConcurrency); + if (resultSetConcurrency == ResultSet.CONCUR_UPDATABLE + || (!useBufferRowIfPossible && !useBufferRowExplicit)) { + return unpackBinaryResultSetRow(fields, rowPacket, + resultSetConcurrency); + } + + if (!canReuseRowPacketForBufferRow) { + this.reusablePacket = new Buffer(rowPacket.getBufLength()); + } + + return new BufferRow(rowPacket, fields, true, getExceptionInterceptor()); } rowPacket.setPosition(rowPacket.getPosition() - 1); @@ -1398,17 +2120,206 @@ return null; } + final ResultSetRow nextRowFast(Field[] fields, int columnCount, + boolean isBinaryEncoded, int resultSetConcurrency, + boolean useBufferRowIfPossible, + boolean useBufferRowExplicit, boolean canReuseRowPacket) + throws SQLException { + try { + int lengthRead = readFully(this.mysqlInput, this.packetHeaderBuf, + 0, 4); + + if (lengthRead < 4) { + forceClose(); + throw new RuntimeException(Messages.getString("MysqlIO.43")); //$NON-NLS-1$ + } + + int packetLength = (this.packetHeaderBuf[0] & 0xff) + + ((this.packetHeaderBuf[1] & 0xff) << 8) + + ((this.packetHeaderBuf[2] & 0xff) << 16); + + // Have we stumbled upon a multi-packet? + if (packetLength == this.maxThreeBytes) { + reuseAndReadPacket(this.reusablePacket, packetLength); + + // Go back to "old" way which uses packets + return nextRow(fields, columnCount, isBinaryEncoded, resultSetConcurrency, + useBufferRowIfPossible, useBufferRowExplicit, + canReuseRowPacket, this.reusablePacket); + } + + // Does this go over the threshold where we should use a BufferRow? + + if (packetLength > this.useBufferRowSizeThreshold) { + reuseAndReadPacket(this.reusablePacket, packetLength); + + // Go back to "old" way which uses packets + return nextRow(fields, columnCount, isBinaryEncoded, resultSetConcurrency, + true, true, + false, this.reusablePacket); + } + + int remaining = packetLength; + + boolean firstTime = true; + + byte[][] rowData = null; + + for (int i = 0; i < columnCount; i++) { + + int sw = this.mysqlInput.read() & 0xff; + remaining--; + + if (firstTime) { + if (sw == 255) { + // error packet - we assemble it whole for "fidelity" + // in case we ever need an entire packet in checkErrorPacket() + // but we could've gotten away with just writing the error code + // and message in it (for now). + Buffer errorPacket = new Buffer(packetLength + HEADER_LENGTH); + errorPacket.setPosition(0); + errorPacket.writeByte(this.packetHeaderBuf[0]); + errorPacket.writeByte(this.packetHeaderBuf[1]); + errorPacket.writeByte(this.packetHeaderBuf[2]); + errorPacket.writeByte((byte) 1); + errorPacket.writeByte((byte)sw); + readFully(this.mysqlInput, errorPacket.getByteBuffer(), 5, packetLength - 1); + errorPacket.setPosition(4); + checkErrorPacket(errorPacket); + } + + if (sw == 254 && packetLength < 9) { + if (this.use41Extensions) { + this.warningCount = (this.mysqlInput.read() & 0xff) + | ((this.mysqlInput.read() & 0xff) << 8); + remaining -= 2; + + if (this.warningCount > 0) { + this.hadWarnings = true; // this is a + // 'latch', it's + // reset by + // sendCommand() + } + + this.oldServerStatus = this.serverStatus; + + this.serverStatus = (this.mysqlInput.read() & 0xff) + | ((this.mysqlInput.read() & 0xff) << 8); + checkTransactionState(oldServerStatus); + + remaining -= 2; + + if (remaining > 0) { + skipFully(this.mysqlInput, remaining); + } + } + + return null; // last data packet + } + + rowData = new byte[columnCount][]; + + firstTime = false; + } + + int len = 0; + + switch (sw) { + case 251: + len = NULL_LENGTH; + break; + + case 252: + len = (this.mysqlInput.read() & 0xff) + | ((this.mysqlInput.read() & 0xff) << 8); + remaining -= 2; + break; + + case 253: + len = (this.mysqlInput.read() & 0xff) + | ((this.mysqlInput.read() & 0xff) << 8) + | ((this.mysqlInput.read() & 0xff) << 16); + + remaining -= 3; + break; + + case 254: + len = (int) ((this.mysqlInput.read() & 0xff) + | ((long) (this.mysqlInput.read() & 0xff) << 8) + | ((long) (this.mysqlInput.read() & 0xff) << 16) + | ((long) (this.mysqlInput.read() & 0xff) << 24) + | ((long) (this.mysqlInput.read() & 0xff) << 32) + | ((long) (this.mysqlInput.read() & 0xff) << 40) + | ((long) (this.mysqlInput.read() & 0xff) << 48) + | ((long) (this.mysqlInput.read() & 0xff) << 56)); + remaining -= 8; + break; + + default: + len = sw; + } + + if (len == NULL_LENGTH) { + rowData[i] = null; + } else if (len == 0) { + rowData[i] = Constants.EMPTY_BYTE_ARRAY; + } else { + rowData[i] = new byte[len]; + + int bytesRead = readFully(this.mysqlInput, rowData[i], 0, + len); + + if (bytesRead != len) { + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, + new IOException(Messages.getString("MysqlIO.43")), getExceptionInterceptor()); + } + + remaining -= bytesRead; + } + } + + if (remaining > 0) { + skipFully(this.mysqlInput, remaining); + } + + return new ByteArrayRow(rowData, getExceptionInterceptor()); + } catch (IOException ioEx) { + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); + } + } + /** * Log-off of the MySQL server and close the socket. * * @throws SQLException DOCUMENT ME! */ final void quit() throws SQLException { - Buffer packet = new Buffer(6); - this.packetSequence = -1; - packet.writeByte((byte) MysqlDefs.QUIT); - send(packet, packet.getPosition()); - forceClose(); + try { + // we're not going to read the response, fixes BUG#56979 Improper connection closing logic + // leads to TIME_WAIT sockets on server + + try { + if (!this.mysqlConnection.isClosed()) { + try { + this.mysqlConnection.shutdownInput(); + } catch (UnsupportedOperationException ex) { + // ignore, some sockets do not support this method + } + } + } catch (IOException ioEx) { + this.connection.getLog().logWarn("Caught while disconnecting...", ioEx); + } + + Buffer packet = new Buffer(6); + this.packetSequence = -1; + this.compressedPacketSequence = -1; + packet.writeByte((byte) MysqlDefs.QUIT); + send(packet, packet.getPosition()); + } finally { + forceClose(); + } } /** @@ -1428,32 +2339,81 @@ void closeStreamer(RowData streamer) throws SQLException { if (this.streamingData == null) { throw SQLError.createSQLException(Messages.getString("MysqlIO.17") //$NON-NLS-1$ - +streamer + Messages.getString("MysqlIO.18")); //$NON-NLS-1$ + +streamer + Messages.getString("MysqlIO.18"), getExceptionInterceptor()); //$NON-NLS-1$ } if (streamer != this.streamingData) { throw SQLError.createSQLException(Messages.getString("MysqlIO.19") //$NON-NLS-1$ +streamer + Messages.getString("MysqlIO.20") //$NON-NLS-1$ +Messages.getString("MysqlIO.21") //$NON-NLS-1$ - +Messages.getString("MysqlIO.22")); //$NON-NLS-1$ + +Messages.getString("MysqlIO.22"), getExceptionInterceptor()); //$NON-NLS-1$ } this.streamingData = null; } - ResultSet readAllResults(Statement callingStatement, int maxRows, + boolean tackOnMoreStreamingResults(ResultSetImpl addingTo) throws SQLException { + if ((this.serverStatus & SERVER_MORE_RESULTS_EXISTS) != 0) { + + boolean moreRowSetsExist = true; + ResultSetImpl currentResultSet = addingTo; + boolean firstTime = true; + + while (moreRowSetsExist) { + if (!firstTime && currentResultSet.reallyResult()) { + break; + } + + firstTime = false; + + Buffer fieldPacket = checkErrorPacket(); + fieldPacket.setPosition(0); + + java.sql.Statement owningStatement = addingTo.getStatement(); + + int maxRows = owningStatement.getMaxRows(); + + // fixme for catalog, isBinary + + ResultSetImpl newResultSet = readResultsForQueryOrUpdate( + (StatementImpl)owningStatement, + maxRows, owningStatement.getResultSetType(), + owningStatement.getResultSetConcurrency(), + true, owningStatement.getConnection().getCatalog(), fieldPacket, + addingTo.isBinaryEncoded, + -1L, null); + + currentResultSet.setNextResultSet(newResultSet); + + currentResultSet = newResultSet; + + moreRowSetsExist = (this.serverStatus & MysqlIO.SERVER_MORE_RESULTS_EXISTS) != 0; + + if (!currentResultSet.reallyResult() && !moreRowSetsExist) { + // special case, we can stop "streaming" + return false; + } + } + + return true; + } + + return false; + } + + ResultSetImpl readAllResults(StatementImpl callingStatement, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Buffer resultPacket, boolean isBinaryEncoded, - long preSentColumnCount, boolean unpackFieldInfo, Field[] metadataFromCache) + long preSentColumnCount, Field[] metadataFromCache) throws SQLException { resultPacket.setPosition(resultPacket.getPosition() - 1); - ResultSet topLevelResultSet = readResultsForQueryOrUpdate(callingStatement, + ResultSetImpl topLevelResultSet = readResultsForQueryOrUpdate(callingStatement, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, resultPacket, isBinaryEncoded, preSentColumnCount, - unpackFieldInfo, metadataFromCache); + metadataFromCache); - ResultSet currentResultSet = topLevelResultSet; + ResultSetImpl currentResultSet = topLevelResultSet; boolean checkForMoreResults = ((this.clientParam & CLIENT_MULTI_RESULTS) != 0); @@ -1465,22 +2425,29 @@ // TODO: We need to support streaming of multiple result sets // if (serverHasMoreResults && streamResults) { - clearInputStream(); - - throw SQLError.createSQLException(Messages.getString("MysqlIO.23"), //$NON-NLS-1$ - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); + //clearInputStream(); +// + //throw SQLError.createSQLException(Messages.getString("MysqlIO.23"), //$NON-NLS-1$ + //SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); + if (topLevelResultSet.getUpdateCount() != -1) { + tackOnMoreStreamingResults(topLevelResultSet); + } + + reclaimLargeReusablePacket(); + + return topLevelResultSet; } boolean moreRowSetsExist = checkForMoreResults & serverHasMoreResults; while (moreRowSetsExist) { Buffer fieldPacket = checkErrorPacket(); fieldPacket.setPosition(0); - - ResultSet newResultSet = readResultsForQueryOrUpdate(callingStatement, + + ResultSetImpl newResultSet = readResultsForQueryOrUpdate(callingStatement, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, fieldPacket, isBinaryEncoded, - preSentColumnCount, unpackFieldInfo, metadataFromCache); + preSentColumnCount, metadataFromCache); currentResultSet.setNextResultSet(newResultSet); @@ -1524,33 +2491,48 @@ * * @throws SQLException if an I/O error or SQL error occurs */ - + final Buffer sendCommand(int command, String extraData, Buffer queryPacket, - boolean skipCheck, String extraDataCharEncoding) + boolean skipCheck, String extraDataCharEncoding, int timeoutMillis) throws SQLException { + this.commandCount++; + // // We cache these locally, per-command, as the checks // for them are in very 'hot' sections of the I/O code // and we save 10-15% in overall performance by doing this... // this.enablePacketDebug = this.connection.getEnablePacketDebug(); - this.traceProtocol = this.connection.getTraceProtocol(); this.readPacketSequence = 0; + int oldTimeout = 0; + + if (timeoutMillis != 0) { + try { + oldTimeout = this.mysqlConnection.getSoTimeout(); + this.mysqlConnection.setSoTimeout(timeoutMillis); + } catch (SocketException e) { + throw SQLError.createCommunicationsException(this.connection, lastPacketSentTimeMs, + lastPacketReceivedTimeMs, e, getExceptionInterceptor()); + } + } + try { - + checkForOutstandingStreamingData(); - + // Clear serverStatus...this value is guarded by an - // external mutex, as you can only ever be processing + // external mutex, as you can only ever be processing // one command at a time + this.oldServerStatus = this.serverStatus; this.serverStatus = 0; this.hadWarnings = false; this.warningCount = 0; this.queryNoIndexUsed = false; this.queryBadIndexUsed = false; - + this.serverQueryWasSlow = false; + // // Compressed input stream needs cleared at beginning // of each command execution... @@ -1582,6 +2564,7 @@ } this.packetSequence = -1; + this.compressedPacketSequence = -1; this.readPacketSequence = 0; this.checkPacketSequence = true; this.sendPacket.clear(); @@ -1602,21 +2585,22 @@ this.connection.parserKnowsUnicode(), this.connection); } } else if (command == MysqlDefs.PROCESS_KILL) { - long id = new Long(extraData).longValue(); + long id = Long.parseLong(extraData); this.sendPacket.writeLong(id); } send(this.sendPacket, this.sendPacket.getPosition()); } else { this.packetSequence = -1; + this.compressedPacketSequence = -1; send(queryPacket, queryPacket.getPosition()); // packet passed by PreparedStatement } } catch (SQLException sqlEx) { // don't wrap SQLExceptions throw sqlEx; } catch (Exception ex) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ex); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ex, getExceptionInterceptor()); } Buffer returnPacket = null; @@ -1633,11 +2617,27 @@ return returnPacket; } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); + } finally { + if (timeoutMillis != 0) { + try { + this.mysqlConnection.setSoTimeout(oldTimeout); + } catch (SocketException e) { + throw SQLError.createCommunicationsException(this.connection, lastPacketSentTimeMs, + lastPacketReceivedTimeMs, e, getExceptionInterceptor()); + } + } } } + private int statementExecutionDepth = 0; + private boolean useAutoSlowLog; + + protected boolean shouldIntercept() { + return this.statementInterceptors != null; + } + /** * Send a query stored in a packet directly to the server. * @@ -1657,232 +2657,396 @@ * * @throws Exception DOCUMENT ME! */ - final ResultSet sqlQueryDirect(Statement callingStatement, String query, - String characterEncoding, Buffer queryPacket, int maxRows, - Connection conn, int resultSetType, int resultSetConcurrency, - boolean streamResults, String catalog, boolean unpackFieldInfo) - throws Exception { - long queryStartTime = 0; - long queryEndTime = 0; + final ResultSetInternalMethods sqlQueryDirect(StatementImpl callingStatement, String query, + String characterEncoding, Buffer queryPacket, int maxRows, + int resultSetType, int resultSetConcurrency, + boolean streamResults, String catalog, Field[] cachedMetadata) + throws Exception { + this.statementExecutionDepth++; - if (query != null) { - - - // We don't know exactly how many bytes we're going to get - // from the query. Since we're dealing with Unicode, the - // max is 2, so pad it (2 * query) + space for headers - int packLength = HEADER_LENGTH + 1 + (query.length() * 2) + 2; + try { + if (this.statementInterceptors != null) { + ResultSetInternalMethods interceptedResults = + invokeStatementInterceptorsPre(query, callingStatement, false); - if (this.sendPacket == null) { - this.sendPacket = new Buffer(packLength); - } else { - this.sendPacket.clear(); - } + if (interceptedResults != null) { + return interceptedResults; + } + } - this.sendPacket.writeByte((byte) MysqlDefs.QUERY); + long queryStartTime = 0; + long queryEndTime = 0; - if (characterEncoding != null) { - if (this.platformDbCharsetMatches) { - this.sendPacket.writeStringNoNull(query, characterEncoding, - this.connection.getServerCharacterEncoding(), - this.connection.parserKnowsUnicode(), - this.connection); - } else { - if (StringUtils.startsWithIgnoreCaseAndWs(query, "LOAD DATA")) { //$NON-NLS-1$ - this.sendPacket.writeBytesNoNull(query.getBytes()); - } else { - this.sendPacket.writeStringNoNull(query, - characterEncoding, - this.connection.getServerCharacterEncoding(), - this.connection.parserKnowsUnicode(), - this.connection); - } - } - } else { - this.sendPacket.writeStringNoNull(query); - } + String statementComment = this.connection.getStatementComment(); + + if (this.connection.getIncludeThreadNamesAsStatementComment()) { + statementComment = (statementComment != null ? statementComment + ", " : "") + "java thread: " + Thread.currentThread().getName(); + } + + if (query != null) { + // We don't know exactly how many bytes we're going to get + // from the query. Since we're dealing with Unicode, the + // max is 2, so pad it (2 * query) + space for headers + int packLength = HEADER_LENGTH + 1 + (query.length() * 3) + 2; - queryPacket = this.sendPacket; - } + byte[] commentAsBytes = null; - byte[] queryBuf = null; - int oldPacketPosition = 0; + if (statementComment != null) { + commentAsBytes = StringUtils.getBytes(statementComment, null, + characterEncoding, this.connection + .getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor()); - - - if (needToGrabQueryFromPacket) { - queryBuf = queryPacket.getByteBuffer(); + packLength += commentAsBytes.length; + packLength += 6; // for /*[space] [space]*/ + } - // save the packet position - oldPacketPosition = queryPacket.getPosition(); + if (this.sendPacket == null) { + this.sendPacket = new Buffer(packLength); + } else { + this.sendPacket.clear(); + } - queryStartTime = getCurrentTimeNanosOrMillis(); - } - - // Send query command and sql query string - Buffer resultPacket = sendCommand(MysqlDefs.QUERY, null, queryPacket, - false, null); + this.sendPacket.writeByte((byte) MysqlDefs.QUERY); - long fetchBeginTime = 0; - long fetchEndTime = 0; + if (commentAsBytes != null) { + this.sendPacket.writeBytesNoNull(Constants.SLASH_STAR_SPACE_AS_BYTES); + this.sendPacket.writeBytesNoNull(commentAsBytes); + this.sendPacket.writeBytesNoNull(Constants.SPACE_STAR_SLASH_SPACE_AS_BYTES); + } - String profileQueryToLog = null; + if (characterEncoding != null) { + if (this.platformDbCharsetMatches) { + this.sendPacket.writeStringNoNull(query, characterEncoding, + this.connection.getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), + this.connection); + } else { + if (StringUtils.startsWithIgnoreCaseAndWs(query, "LOAD DATA")) { //$NON-NLS-1$ + this.sendPacket.writeBytesNoNull(StringUtils.getBytes(query)); + } else { + this.sendPacket.writeStringNoNull(query, + characterEncoding, + this.connection.getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), + this.connection); + } + } + } else { + this.sendPacket.writeStringNoNull(query); + } - boolean queryWasSlow = false; + queryPacket = this.sendPacket; + } - if (this.profileSql || this.logSlowQueries) { - queryEndTime = getCurrentTimeNanosOrMillis(); + byte[] queryBuf = null; + int oldPacketPosition = 0; - boolean shouldExtractQuery = false; + if (needToGrabQueryFromPacket) { + queryBuf = queryPacket.getByteBuffer(); - if (this.profileSql) { - shouldExtractQuery = true; - } else if (this.logSlowQueries) { + // save the packet position + oldPacketPosition = queryPacket.getPosition(); - if ((queryEndTime - queryStartTime) > this.slowQueryThreshold) { - shouldExtractQuery = true; - queryWasSlow = true; - } - } + queryStartTime = getCurrentTimeNanosOrMillis(); + } + + if (this.autoGenerateTestcaseScript) { + String testcaseQuery = null; - if (shouldExtractQuery) { - // Extract the actual query from the network packet - boolean truncated = false; + if (query != null) { + if (statementComment != null) { + testcaseQuery = "/* " + statementComment + " */ " + query; + } else { + testcaseQuery = query; + } + } else { + testcaseQuery = StringUtils.toString(queryBuf, 5, + (oldPacketPosition - 5)); + } - int extractPosition = oldPacketPosition; + StringBuffer debugBuf = new StringBuffer(testcaseQuery.length() + 32); + this.connection.generateConnectionCommentBlock(debugBuf); + debugBuf.append(testcaseQuery); + debugBuf.append(';'); + this.connection.dumpTestcaseQuery(debugBuf.toString()); + } - if (oldPacketPosition > this.connection.getMaxQuerySizeToLog()) { - extractPosition = this.connection.getMaxQuerySizeToLog() + 5; - truncated = true; - } + // Send query command and sql query string + Buffer resultPacket = sendCommand(MysqlDefs.QUERY, null, queryPacket, + false, null, 0); - profileQueryToLog = new String(queryBuf, 5, - (extractPosition - 5)); + long fetchBeginTime = 0; + long fetchEndTime = 0; - if (truncated) { - profileQueryToLog += Messages.getString("MysqlIO.25"); //$NON-NLS-1$ - } - } + String profileQueryToLog = null; - fetchBeginTime = queryEndTime; - } - - if (this.autoGenerateTestcaseScript) { - String testcaseQuery = null; - - if (query != null) { - testcaseQuery = query; - } else { - testcaseQuery = new String(queryBuf, 5, - (oldPacketPosition - 5)); - } - - StringBuffer debugBuf = new StringBuffer(testcaseQuery.length() + 32); - this.connection.generateConnectionCommentBlock(debugBuf); - debugBuf.append(testcaseQuery); - debugBuf.append(';'); - this.connection.dumpTestcaseQuery(debugBuf.toString()); - } - - ResultSet rs = readAllResults(callingStatement, maxRows, resultSetType, - resultSetConcurrency, streamResults, catalog, resultPacket, - false, -1L, unpackFieldInfo, null /* we don't need metadata for cached MD in this case */); + boolean queryWasSlow = false; - if (queryWasSlow) { - StringBuffer mesgBuf = new StringBuffer(48 + - profileQueryToLog.length()); - - mesgBuf.append(Messages.getString("MysqlIO.SlowQuery", - new Object[] {new Long(this.slowQueryThreshold), - queryTimingUnits, - new Long(queryEndTime - queryStartTime)})); - mesgBuf.append(profileQueryToLog); + if (this.profileSql || this.logSlowQueries) { + queryEndTime = getCurrentTimeNanosOrMillis(); - ProfileEventSink eventSink = ProfileEventSink.getInstance(this.connection); + boolean shouldExtractQuery = false; - eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_SLOW_QUERY, - "", catalog, this.connection.getId(), //$NON-NLS-1$ - (callingStatement != null) ? callingStatement.getId() : 999, - rs.resultId, System.currentTimeMillis(), - (int) (queryEndTime - queryStartTime), queryTimingUnits, null, - new Throwable(), mesgBuf.toString())); + if (this.profileSql) { + shouldExtractQuery = true; + } else if (this.logSlowQueries) { + long queryTime = queryEndTime - queryStartTime; + + boolean logSlow = false; + + if (!this.useAutoSlowLog) { + logSlow = queryTime > this.connection.getSlowQueryThresholdMillis(); + } else { + logSlow = this.connection.isAbonormallyLongQuery(queryTime); + + this.connection.reportQueryTime(queryTime); + } + + if (logSlow) { + shouldExtractQuery = true; + queryWasSlow = true; + } + } - if (this.connection.getExplainSlowQueries()) { - if (oldPacketPosition < MAX_QUERY_SIZE_TO_EXPLAIN) { - explainSlowQuery(queryPacket.getBytes(5, - (oldPacketPosition - 5)), profileQueryToLog); - } else { - this.connection.getLog().logWarn(Messages.getString( - "MysqlIO.28") //$NON-NLS-1$ - +MAX_QUERY_SIZE_TO_EXPLAIN + - Messages.getString("MysqlIO.29")); //$NON-NLS-1$ - } - } - } + if (shouldExtractQuery) { + // Extract the actual query from the network packet + boolean truncated = false; - if (this.profileSql) { - fetchEndTime = getCurrentTimeNanosOrMillis(); + int extractPosition = oldPacketPosition; - ProfileEventSink eventSink = ProfileEventSink.getInstance(this.connection); + if (oldPacketPosition > this.connection.getMaxQuerySizeToLog()) { + extractPosition = this.connection.getMaxQuerySizeToLog() + 5; + truncated = true; + } - eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_QUERY, - "", catalog, this.connection.getId(), //$NON-NLS-1$ - (callingStatement != null) ? callingStatement.getId() : 999, - rs.resultId, System.currentTimeMillis(), - (queryEndTime - queryStartTime), this.queryTimingUnits, - null, - new Throwable(), profileQueryToLog)); + profileQueryToLog = StringUtils.toString(queryBuf, 5, + (extractPosition - 5)); - eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_FETCH, - "", catalog, this.connection.getId(), //$NON-NLS-1$ - (callingStatement != null) ? callingStatement.getId() : 999, - rs.resultId, System.currentTimeMillis(), - (fetchEndTime - fetchBeginTime), this.queryTimingUnits, - null, - new Throwable(), null)); + if (truncated) { + profileQueryToLog += Messages.getString("MysqlIO.25"); //$NON-NLS-1$ + } + } - if (this.queryBadIndexUsed) { - eventSink.consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_SLOW_QUERY, "", catalog, //$NON-NLS-1$ - this.connection.getId(), - (callingStatement != null) ? callingStatement.getId() - : 999, rs.resultId, - System.currentTimeMillis(), - (queryEndTime - queryStartTime), this.queryTimingUnits, - null, - new Throwable(), - Messages.getString("MysqlIO.33") //$NON-NLS-1$ - +profileQueryToLog)); - } + fetchBeginTime = queryEndTime; + } - if (this.queryNoIndexUsed) { - eventSink.consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_SLOW_QUERY, "", catalog, //$NON-NLS-1$ - this.connection.getId(), - (callingStatement != null) ? callingStatement.getId() - : 999, rs.resultId, - System.currentTimeMillis(), - (queryEndTime - queryStartTime), this.queryTimingUnits, - null, - new Throwable(), - Messages.getString("MysqlIO.35") //$NON-NLS-1$ - +profileQueryToLog)); - } - } + ResultSetInternalMethods rs = readAllResults(callingStatement, maxRows, resultSetType, + resultSetConcurrency, streamResults, catalog, resultPacket, + false, -1L, cachedMetadata); - if (this.hadWarnings) { - scanForAndThrowDataTruncation(); - } + if (queryWasSlow && !this.serverQueryWasSlow /* don't log slow queries twice */) { + StringBuffer mesgBuf = new StringBuffer(48 + + profileQueryToLog.length()); - return rs; + mesgBuf.append(Messages.getString("MysqlIO.SlowQuery", + new Object[] {String.valueOf(this.useAutoSlowLog ? + " 95% of all queries " : this.slowQueryThreshold), + queryTimingUnits, + Long.valueOf(queryEndTime - queryStartTime)})); + mesgBuf.append(profileQueryToLog); + + ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); + + eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_SLOW_QUERY, + "", catalog, this.connection.getId(), //$NON-NLS-1$ + (callingStatement != null) ? callingStatement.getId() : 999, + ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), + (int) (queryEndTime - queryStartTime), queryTimingUnits, null, + LogUtils.findCallingClassAndMethod(new Throwable()), mesgBuf.toString())); + + if (this.connection.getExplainSlowQueries()) { + if (oldPacketPosition < MAX_QUERY_SIZE_TO_EXPLAIN) { + explainSlowQuery(queryPacket.getBytes(5, + (oldPacketPosition - 5)), profileQueryToLog); + } else { + this.connection.getLog().logWarn(Messages.getString( + "MysqlIO.28") //$NON-NLS-1$ + +MAX_QUERY_SIZE_TO_EXPLAIN + + Messages.getString("MysqlIO.29")); //$NON-NLS-1$ + } + } + } + + if (this.logSlowQueries) { + + ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); + + if (this.queryBadIndexUsed && this.profileSql) { + eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_SLOW_QUERY, "", catalog, //$NON-NLS-1$ + this.connection.getId(), + (callingStatement != null) ? callingStatement.getId() + : 999, ((ResultSetImpl)rs).resultId, + System.currentTimeMillis(), + (queryEndTime - queryStartTime), this.queryTimingUnits, + null, + LogUtils.findCallingClassAndMethod(new Throwable()), + Messages.getString("MysqlIO.33") //$NON-NLS-1$ + +profileQueryToLog)); + } + + if (this.queryNoIndexUsed && this.profileSql) { + eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_SLOW_QUERY, "", catalog, //$NON-NLS-1$ + this.connection.getId(), + (callingStatement != null) ? callingStatement.getId() + : 999, ((ResultSetImpl)rs).resultId, + System.currentTimeMillis(), + (queryEndTime - queryStartTime), this.queryTimingUnits, + null, + LogUtils.findCallingClassAndMethod(new Throwable()), + Messages.getString("MysqlIO.35") //$NON-NLS-1$ + +profileQueryToLog)); + } + + if (this.serverQueryWasSlow && this.profileSql) { + eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_SLOW_QUERY, "", catalog, //$NON-NLS-1$ + this.connection.getId(), + (callingStatement != null) ? callingStatement.getId() + : 999, ((ResultSetImpl)rs).resultId, + System.currentTimeMillis(), + (queryEndTime - queryStartTime), this.queryTimingUnits, + null, + LogUtils.findCallingClassAndMethod(new Throwable()), + Messages.getString("MysqlIO.ServerSlowQuery") //$NON-NLS-1$ + +profileQueryToLog)); + } + } + + if (this.profileSql) { + fetchEndTime = getCurrentTimeNanosOrMillis(); + + ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); + + eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_QUERY, + "", catalog, this.connection.getId(), //$NON-NLS-1$ + (callingStatement != null) ? callingStatement.getId() : 999, + ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), + (queryEndTime - queryStartTime), this.queryTimingUnits, + null, + LogUtils.findCallingClassAndMethod(new Throwable()), profileQueryToLog)); + + eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_FETCH, + "", catalog, this.connection.getId(), //$NON-NLS-1$ + (callingStatement != null) ? callingStatement.getId() : 999, + ((ResultSetImpl)rs).resultId, System.currentTimeMillis(), + (fetchEndTime - fetchBeginTime), this.queryTimingUnits, + null, + LogUtils.findCallingClassAndMethod(new Throwable()), null)); + } + + if (this.hadWarnings) { + scanForAndThrowDataTruncation(); + } + + if (this.statementInterceptors != null) { + ResultSetInternalMethods interceptedResults = invokeStatementInterceptorsPost( + query, callingStatement, rs, false, null); + + if (interceptedResults != null) { + rs = interceptedResults; + } + } + + return rs; + } catch (SQLException sqlEx) { + if (this.statementInterceptors != null) { + invokeStatementInterceptorsPost( + query, callingStatement, null, false, sqlEx); // we don't do anything with the result set in this case + } + + if (callingStatement != null) { + synchronized (callingStatement.cancelTimeoutMutex) { + if (callingStatement.wasCancelled) { + SQLException cause = null; + + if (callingStatement.wasCancelledByTimeout) { + cause = new MySQLTimeoutException(); + } else { + cause = new MySQLStatementCancelledException(); + } + + callingStatement.resetCancelledState(); + + throw cause; + } + } + } + + throw sqlEx; + } finally { + this.statementExecutionDepth--; + } } + ResultSetInternalMethods invokeStatementInterceptorsPre(String sql, + Statement interceptedStatement, boolean forceExecute) throws SQLException { + ResultSetInternalMethods previousResultSet = null; + + for (int i = 0, s = this.statementInterceptors.size(); i < s; i++) { + StatementInterceptorV2 interceptor = this.statementInterceptors.get(i); + + boolean executeTopLevelOnly = interceptor.executeTopLevelOnly(); + boolean shouldExecute = (executeTopLevelOnly && (this.statementExecutionDepth == 1 || forceExecute)) + || (!executeTopLevelOnly); + + if (shouldExecute) { + String sqlToInterceptor = sql; + + //if (interceptedStatement instanceof PreparedStatement) { + // sqlToInterceptor = ((PreparedStatement) interceptedStatement) + // .asSql(); + //} + + ResultSetInternalMethods interceptedResultSet = interceptor + .preProcess(sqlToInterceptor, interceptedStatement, + this.connection); + + if (interceptedResultSet != null) { + previousResultSet = interceptedResultSet; + } + } + } + + return previousResultSet; + } + + ResultSetInternalMethods invokeStatementInterceptorsPost( + String sql, Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, boolean forceExecute, SQLException statementException) throws SQLException { + + for (int i = 0, s = this.statementInterceptors.size(); i < s; i++) { + StatementInterceptorV2 interceptor = this.statementInterceptors.get(i); + + boolean executeTopLevelOnly = interceptor.executeTopLevelOnly(); + boolean shouldExecute = (executeTopLevelOnly && (this.statementExecutionDepth == 1 || forceExecute)) + || (!executeTopLevelOnly); + + if (shouldExecute) { + String sqlToInterceptor = sql; + + ResultSetInternalMethods interceptedResultSet = interceptor + .postProcess(sqlToInterceptor, interceptedStatement, + originalResultSet, this.connection, this.warningCount, + this.queryNoIndexUsed, this.queryBadIndexUsed, statementException); + + if (interceptedResultSet != null) { + originalResultSet = interceptedResultSet; + } + } + } + + return originalResultSet; + } + private void calculateSlowQueryThreshold() { this.slowQueryThreshold = this.connection.getSlowQueryThresholdMillis(); - + if (this.connection.getUseNanosForElapsedTime()) { long nanosThreshold = this.connection.getSlowQueryThresholdNanos(); - + if (nanosThreshold != 0) { this.slowQueryThreshold = nanosThreshold; } else { @@ -1895,11 +3059,11 @@ if (this.useNanosForElapsedTime) { return Util.getCurrentTimeNanosOrMillis(); } - + return System.currentTimeMillis(); } - /** + /** * Returns the host this IO is connected to * * @return DOCUMENT ME! @@ -1951,7 +3115,7 @@ return false; } - // newer than major + // newer than major return true; } @@ -1994,34 +3158,34 @@ int count = in.read(b, off + n, len - n); if (count < 0) { - throw new EOFException(Messages.getString("MysqlIO.EOF", - new Object[] {new Integer(len), new Integer(n)})); + throw new EOFException(Messages.getString("MysqlIO.EOF", + new Object[] {Integer.valueOf(len), Integer.valueOf(n)})); } n += count; } return n; } - + private final long skipFully(InputStream in, long len) throws IOException { if (len < 0) { throw new IOException("Negative skip length not allowed"); } - + long n = 0; - + while (n < len) { long count = in.skip(len - n); - + if (count < 0) { - throw new EOFException(Messages.getString("MysqlIO.EOF", - new Object[] {new Long(len), new Long(n)})); + throw new EOFException(Messages.getString("MysqlIO.EOF", + new Object[] {Long.valueOf(len), Long.valueOf(n)})); } - + n += count; } - + return n; } @@ -2045,11 +3209,11 @@ * * @throws SQLException if an error occurs while reading the rows */ - private final ResultSet readResultsForQueryOrUpdate( - Statement callingStatement, int maxRows, int resultSetType, + protected final ResultSetImpl readResultsForQueryOrUpdate( + StatementImpl callingStatement, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Buffer resultPacket, boolean isBinaryEncoded, long preSentColumnCount, - boolean unpackFieldInfo, Field[] metadataFromCache) throws SQLException { + Field[] metadataFromCache) throws SQLException { long columnCount = resultPacket.readFieldLength(); if (columnCount == 0) { @@ -2065,17 +3229,17 @@ if (this.platformDbCharsetMatches) { fileName = ((charEncoding != null) - ? resultPacket.readString(charEncoding) + ? resultPacket.readString(charEncoding, getExceptionInterceptor()) : resultPacket.readString()); } else { fileName = resultPacket.readString(); } return sendFileToServer(callingStatement, fileName); } else { - com.mysql.jdbc.ResultSet results = getResultSet(callingStatement, + com.mysql.jdbc.ResultSetImpl results = getResultSet(callingStatement, columnCount, maxRows, resultSetType, resultSetConcurrency, - streamResults, catalog, isBinaryEncoded, unpackFieldInfo, + streamResults, catalog, isBinaryEncoded, metadataFromCache); return results; @@ -2086,17 +3250,17 @@ return ((((a) + (l)) - 1) & ~((l) - 1)); } - private com.mysql.jdbc.ResultSet buildResultSetWithRows( - Statement callingStatement, String catalog, + private com.mysql.jdbc.ResultSetImpl buildResultSetWithRows( + StatementImpl callingStatement, String catalog, com.mysql.jdbc.Field[] fields, RowData rows, int resultSetType, int resultSetConcurrency, boolean isBinaryEncoded) throws SQLException { - ResultSet rs = null; + ResultSetImpl rs = null; switch (resultSetConcurrency) { case java.sql.ResultSet.CONCUR_READ_ONLY: - rs = new com.mysql.jdbc.ResultSet(catalog, fields, rows, - this.connection, callingStatement); + rs = com.mysql.jdbc.ResultSetImpl.getInstance(catalog, fields, rows, + this.connection, callingStatement, false); if (isBinaryEncoded) { rs.setBinaryEncoded(); @@ -2105,14 +3269,14 @@ break; case java.sql.ResultSet.CONCUR_UPDATABLE: - rs = new com.mysql.jdbc.UpdatableResultSet(catalog, fields, rows, - this.connection, callingStatement); + rs = com.mysql.jdbc.ResultSetImpl.getInstance(catalog, fields, rows, + this.connection, callingStatement, true); break; default: - return new com.mysql.jdbc.ResultSet(catalog, fields, rows, - this.connection, callingStatement); + return com.mysql.jdbc.ResultSetImpl.getInstance(catalog, fields, rows, + this.connection, callingStatement, false); } rs.setResultSetType(resultSetType); @@ -2121,8 +3285,8 @@ return rs; } - private com.mysql.jdbc.ResultSet buildResultSetWithUpdates( - Statement callingStatement, Buffer resultPacket) + private com.mysql.jdbc.ResultSetImpl buildResultSetWithUpdates( + StatementImpl callingStatement, Buffer resultPacket) throws SQLException { long updateCount = -1; long updateID = -1; @@ -2138,8 +3302,11 @@ } if (this.use41Extensions) { + // oldStatus set in sendCommand() this.serverStatus = resultPacket.readInt(); + checkTransactionState(oldServerStatus); + this.warningCount = resultPacket.readInt(); if (this.warningCount > 0) { @@ -2148,41 +3315,49 @@ resultPacket.readByte(); // advance pointer - if (this.profileSql) { - this.queryNoIndexUsed = (this.serverStatus & - SERVER_QUERY_NO_GOOD_INDEX_USED) != 0; - this.queryBadIndexUsed = (this.serverStatus & - SERVER_QUERY_NO_INDEX_USED) != 0; - } + setServerSlowQueryFlags(); } if (this.connection.isReadInfoMsgEnabled()) { - info = resultPacket.readString(); + info = resultPacket.readString(this.connection.getErrorMessageEncoding(), getExceptionInterceptor()); } } catch (Exception ex) { - throw SQLError.createSQLException(SQLError.get( - SQLError.SQL_STATE_GENERAL_ERROR) + ": " //$NON-NLS-1$ - +ex.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR, -1); + SQLException sqlEx = SQLError.createSQLException(SQLError.get( + SQLError.SQL_STATE_GENERAL_ERROR), SQLError.SQL_STATE_GENERAL_ERROR, -1, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; } - ResultSet updateRs = new com.mysql.jdbc.ResultSet(updateCount, + ResultSetInternalMethods updateRs = com.mysql.jdbc.ResultSetImpl.getInstance(updateCount, updateID, this.connection, callingStatement); if (info != null) { - updateRs.setServerInfo(info); + ((com.mysql.jdbc.ResultSetImpl)updateRs).setServerInfo(info); } - return updateRs; + return (com.mysql.jdbc.ResultSetImpl)updateRs; } + private void setServerSlowQueryFlags() { + this.queryBadIndexUsed = (this.serverStatus & + SERVER_QUERY_NO_GOOD_INDEX_USED) != 0; + this.queryNoIndexUsed = (this.serverStatus & + SERVER_QUERY_NO_INDEX_USED) != 0; + this.serverQueryWasSlow = (this.serverStatus & + SERVER_QUERY_WAS_SLOW) != 0; + } + private void checkForOutstandingStreamingData() throws SQLException { if (this.streamingData != null) { - if (!this.connection.getClobberStreamingResults()) { + boolean shouldClobber = this.connection.getClobberStreamingResults(); + + if (!shouldClobber) { throw SQLError.createSQLException(Messages.getString("MysqlIO.39") //$NON-NLS-1$ +this.streamingData + Messages.getString("MysqlIO.40") //$NON-NLS-1$ +Messages.getString("MysqlIO.41") //$NON-NLS-1$ - +Messages.getString("MysqlIO.42")); //$NON-NLS-1$ + +Messages.getString("MysqlIO.42"), getExceptionInterceptor()); //$NON-NLS-1$ } // Close the result set @@ -2193,51 +3368,55 @@ } } - private Buffer compressPacket(Buffer packet, int offset, int packetLen, - int headerLength) throws SQLException { - packet.writeLongInt(packetLen - headerLength); - packet.writeByte((byte) 0); // wrapped packet has 0 packet seq. + /** + * + * @param packet original uncompressed MySQL packet + * @param offset begin of MySQL packet header + * @param packetLen real length of packet + * @return compressed packet with header + * @throws SQLException + */ + private Buffer compressPacket(Buffer packet, int offset, int packetLen) throws SQLException { - int lengthToWrite = 0; - int compressedLength = 0; - byte[] bytesToCompress = packet.getByteBuffer(); - byte[] compressedBytes = null; - int offsetWrite = 0; + // uncompressed payload by default + int compressedLength = packetLen; + int uncompressedLength = 0; + byte[] compressedBytes = null; + int offsetWrite = offset; - if (packetLen < MIN_COMPRESS_LEN) { - lengthToWrite = packetLen; - compressedBytes = packet.getByteBuffer(); - compressedLength = 0; - offsetWrite = offset; - } else { - compressedBytes = new byte[bytesToCompress.length * 2]; + if (packetLen < MIN_COMPRESS_LEN) { + compressedBytes = packet.getByteBuffer(); + } else { + byte[] bytesToCompress = packet.getByteBuffer(); + compressedBytes = new byte[bytesToCompress.length * 2]; + + if (this.deflater == null) { + this.deflater = new Deflater(); + } this.deflater.reset(); this.deflater.setInput(bytesToCompress, offset, packetLen); this.deflater.finish(); - int compLen = this.deflater.deflate(compressedBytes); + compressedLength = this.deflater.deflate(compressedBytes); - if (compLen > packetLen) { - lengthToWrite = packetLen; + if (compressedLength > packetLen) { + // if compressed data is greater then uncompressed then send uncompressed compressedBytes = packet.getByteBuffer(); - compressedLength = 0; - offsetWrite = offset; + compressedLength = packetLen; } else { - lengthToWrite = compLen; - headerLength += COMP_HEADER_LENGTH; - compressedLength = packetLen; + uncompressedLength = packetLen; + offsetWrite = 0; } } - Buffer compressedPacket = new Buffer(packetLen + headerLength); + Buffer compressedPacket = new Buffer(HEADER_LENGTH + COMP_HEADER_LENGTH + compressedLength); compressedPacket.setPosition(0); - compressedPacket.writeLongInt(lengthToWrite); - compressedPacket.writeByte(this.packetSequence); compressedPacket.writeLongInt(compressedLength); - compressedPacket.writeBytesNoNull(compressedBytes, offsetWrite, - lengthToWrite); + compressedPacket.writeByte(this.compressedPacketSequence); + compressedPacket.writeLongInt(uncompressedLength); + compressedPacket.writeBytesNoNull(compressedBytes, offsetWrite, compressedLength); return compressedPacket; } @@ -2253,33 +3432,32 @@ this.hadWarnings = true; // this is a 'latch', it's reset by sendCommand() } + this.oldServerStatus = this.serverStatus; this.serverStatus = rowPacket.readInt(); + checkTransactionState(oldServerStatus); - if (this.profileSql) { - this.queryNoIndexUsed = (this.serverStatus & - SERVER_QUERY_NO_GOOD_INDEX_USED) != 0; - this.queryBadIndexUsed = (this.serverStatus & - SERVER_QUERY_NO_INDEX_USED) != 0; - } + setServerSlowQueryFlags(); } } - + private SocketFactory createSocketFactory() throws SQLException { try { if (this.socketFactoryClassName == null) { throw SQLError.createSQLException(Messages.getString("MysqlIO.75"), //$NON-NLS-1$ - SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, getExceptionInterceptor()); } return (SocketFactory) (Class.forName(this.socketFactoryClassName) .newInstance()); } catch (Exception ex) { - throw SQLError.createSQLException(Messages.getString("MysqlIO.76") //$NON-NLS-1$ + SQLException sqlEx = SQLError.createSQLException(Messages.getString("MysqlIO.76") //$NON-NLS-1$ +this.socketFactoryClassName + - Messages.getString("MysqlIO.77") + ex.toString() //$NON-NLS-1$ - +(this.connection.getParanoid() ? "" //$NON-NLS-1$ - : Util.stackTraceToString(ex)), - SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); + Messages.getString("MysqlIO.77"), + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, getExceptionInterceptor()); + + sqlEx.initCause(ex); + + throw sqlEx; } } @@ -2347,31 +3525,33 @@ this.packetDebugRingBuffer.addLast(packetDump); } - + private RowData readSingleRowSet(long columnCount, int maxRows, int resultSetConcurrency, boolean isBinaryEncoded, Field[] fields) throws SQLException { RowData rowData; - ArrayList rows = new ArrayList(); + ArrayList rows = new ArrayList(); + boolean useBufferRowExplicit = useBufferRowExplicit(fields); + // Now read the data - Object rowBytes = nextRow(fields, (int) columnCount, isBinaryEncoded, - resultSetConcurrency); - + ResultSetRow row = nextRow(fields, (int) columnCount, isBinaryEncoded, + resultSetConcurrency, false, useBufferRowExplicit, false, null); + int rowCount = 0; - if (rowBytes != null) { - rows.add(rowBytes); + if (row != null) { + rows.add(row); rowCount = 1; } - while (rowBytes != null) { - rowBytes = nextRow(fields, (int) columnCount, isBinaryEncoded, - resultSetConcurrency); + while (row != null) { + row = nextRow(fields, (int) columnCount, isBinaryEncoded, + resultSetConcurrency, false, useBufferRowExplicit, false, null); - if (rowBytes != null) { + if (row != null) { if ((maxRows == -1) || (rowCount < maxRows)) { - rows.add(rowBytes); + rows.add(row); rowCount++; } } @@ -2382,7 +3562,25 @@ return rowData; } - /** + public static boolean useBufferRowExplicit(Field[] fields) { + if (fields == null) { + return false; + } + + for (int i = 0; i < fields.length; i++) { + switch (fields[i].getSQLType()) { + case Types.BLOB: + case Types.CLOB: + case Types.LONGVARBINARY: + case Types.LONGVARCHAR: + return true; + } + } + + return false; + } + + /** * Don't hold on to overly-large packets */ private void reclaimLargeReusablePacket() { @@ -2402,51 +3600,60 @@ * @throws SQLException DOCUMENT ME! * @throws SQLException DOCUMENT ME! */ - private final Buffer reuseAndReadPacket(Buffer reuse) + private final Buffer reuseAndReadPacket(Buffer reuse) throws SQLException { + return reuseAndReadPacket(reuse, -1); + } + + private final Buffer reuseAndReadPacket(Buffer reuse, int existingPacketLength) throws SQLException { - + try { reuse.setWasMultiPacket(false); - - int lengthRead = readFully(this.mysqlInput, - this.packetHeaderBuf, 0, 4); - - if (lengthRead < 4) { - forceClose(); - throw new IOException(Messages.getString("MysqlIO.43")); //$NON-NLS-1$ + int packetLength = 0; + + if (existingPacketLength == -1) { + int lengthRead = readFully(this.mysqlInput, + this.packetHeaderBuf, 0, 4); + + if (lengthRead < 4) { + forceClose(); + throw new IOException(Messages.getString("MysqlIO.43")); //$NON-NLS-1$ + } + + packetLength = (this.packetHeaderBuf[0] & 0xff) + + ((this.packetHeaderBuf[1] & 0xff) << 8) + + ((this.packetHeaderBuf[2] & 0xff) << 16); + } else { + packetLength = existingPacketLength; } - - int packetLength = (this.packetHeaderBuf[0] & 0xff) + - ((this.packetHeaderBuf[1] & 0xff) << 8) + - ((this.packetHeaderBuf[2] & 0xff) << 16); - + if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); - + traceMessageBuf.append(Messages.getString("MysqlIO.44")); //$NON-NLS-1$ traceMessageBuf.append(packetLength); traceMessageBuf.append(Messages.getString("MysqlIO.45")); //$NON-NLS-1$ traceMessageBuf.append(StringUtils.dumpAsHex( this.packetHeaderBuf, 4)); - + this.connection.getLog().logTrace(traceMessageBuf.toString()); } - + byte multiPacketSeq = this.packetHeaderBuf[3]; - + if (!this.packetSequenceReset) { if (this.enablePacketDebug && this.checkPacketSequence) { checkPacketSequencing(multiPacketSeq); } } else { this.packetSequenceReset = false; } - + this.readPacketSequence = multiPacketSeq; - + // Set the Buffer to it's original state reuse.setPosition(0); - + // Do we need to re-alloc the byte buffer? // // Note: We actually check the length of the buffer, @@ -2456,260 +3663,272 @@ if (reuse.getByteBuffer().length <= packetLength) { reuse.setByteBuffer(new byte[packetLength + 1]); } - + // Set the new length reuse.setBufLength(packetLength); - + // Read the data from the server int numBytesRead = readFully(this.mysqlInput, reuse.getByteBuffer(), 0, packetLength); - + if (numBytesRead != packetLength) { throw new IOException("Short read, expected " + packetLength + " bytes, only read " + numBytesRead); } - + if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); - + traceMessageBuf.append(Messages.getString("MysqlIO.46")); //$NON-NLS-1$ traceMessageBuf.append(getPacketDumpToLog(reuse, packetLength)); - + this.connection.getLog().logTrace(traceMessageBuf.toString()); } - + if (this.enablePacketDebug) { enqueuePacketForDebugging(false, true, 0, this.packetHeaderBuf, reuse); } - + boolean isMultiPacket = false; - + if (packetLength == this.maxThreeBytes) { reuse.setPosition(this.maxThreeBytes); - - int packetEndPoint = packetLength; - + // it's multi-packet isMultiPacket = true; - - lengthRead = readFully(this.mysqlInput, - this.packetHeaderBuf, 0, 4); - - if (lengthRead < 4) { - forceClose(); - throw new IOException(Messages.getString("MysqlIO.47")); //$NON-NLS-1$ - } - - packetLength = (this.packetHeaderBuf[0] & 0xff) + - ((this.packetHeaderBuf[1] & 0xff) << 8) + - ((this.packetHeaderBuf[2] & 0xff) << 16); - - Buffer multiPacket = new Buffer(packetLength); - boolean firstMultiPkt = true; - - while (true) { - if (!firstMultiPkt) { - lengthRead = readFully(this.mysqlInput, - this.packetHeaderBuf, 0, 4); - - if (lengthRead < 4) { - forceClose(); - throw new IOException(Messages.getString( - "MysqlIO.48")); //$NON-NLS-1$ - } - - packetLength = (this.packetHeaderBuf[0] & 0xff) + - ((this.packetHeaderBuf[1] & 0xff) << 8) + - ((this.packetHeaderBuf[2] & 0xff) << 16); - } else { - firstMultiPkt = false; - } - - if (!this.useNewLargePackets && (packetLength == 1)) { - clearInputStream(); - - break; - } else if (packetLength < this.maxThreeBytes) { - byte newPacketSeq = this.packetHeaderBuf[3]; - - if (newPacketSeq != (multiPacketSeq + 1)) { - throw new IOException(Messages.getString( - "MysqlIO.49")); //$NON-NLS-1$ - } - - multiPacketSeq = newPacketSeq; - - // Set the Buffer to it's original state - multiPacket.setPosition(0); - - // Set the new length - multiPacket.setBufLength(packetLength); - - // Read the data from the server - byte[] byteBuf = multiPacket.getByteBuffer(); - int lengthToWrite = packetLength; - - int bytesRead = readFully(this.mysqlInput, byteBuf, - 0, packetLength); - - if (bytesRead != lengthToWrite) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, - SQLError.createSQLException(Messages.getString( - "MysqlIO.50") //$NON-NLS-1$ - +lengthToWrite + - Messages.getString("MysqlIO.51") + - bytesRead //$NON-NLS-1$ - +".")); //$NON-NLS-1$ - } - - reuse.writeBytesNoNull(byteBuf, 0, lengthToWrite); - - packetEndPoint += lengthToWrite; - - break; // end of multipacket sequence - } - - byte newPacketSeq = this.packetHeaderBuf[3]; - - if (newPacketSeq != (multiPacketSeq + 1)) { - throw new IOException(Messages.getString( - "MysqlIO.53")); //$NON-NLS-1$ - } - - multiPacketSeq = newPacketSeq; - - // Set the Buffer to it's original state - multiPacket.setPosition(0); - - // Set the new length - multiPacket.setBufLength(packetLength); - - // Read the data from the server - byte[] byteBuf = multiPacket.getByteBuffer(); - int lengthToWrite = packetLength; - - int bytesRead = readFully(this.mysqlInput, byteBuf, 0, - packetLength); - - if (bytesRead != lengthToWrite) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, - SQLError.createSQLException(Messages.getString( - "MysqlIO.54") //$NON-NLS-1$ - +lengthToWrite + - Messages.getString("MysqlIO.55") //$NON-NLS-1$ - +bytesRead + ".")); //$NON-NLS-1$ - } - - reuse.writeBytesNoNull(byteBuf, 0, lengthToWrite); - - packetEndPoint += lengthToWrite; - } - - reuse.setPosition(0); - reuse.setWasMultiPacket(true); + + packetLength = readRemainingMultiPackets(reuse, multiPacketSeq); } - + if (!isMultiPacket) { reuse.getByteBuffer()[packetLength] = 0; // Null-termination } - + + if (this.connection.getMaintainTimeStats()) { + this.lastPacketReceivedTimeMs = System.currentTimeMillis(); + } + return reuse; } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } catch (OutOfMemoryError oom) { try { // _Try_ this clearInputStream(); - } finally { - try { - this.connection.realClose(false, false, true, oom); - } finally { - throw oom; - } - } + } catch (Exception ex) { + } + try { + this.connection.realClose(false, false, true, oom); + } catch (Exception ex) { + } + throw oom; } - + } + private int readRemainingMultiPackets(Buffer reuse, byte multiPacketSeq) + throws IOException, SQLException { + int lengthRead; + int packetLength; + lengthRead = readFully(this.mysqlInput, + this.packetHeaderBuf, 0, 4); + + if (lengthRead < 4) { + forceClose(); + throw new IOException(Messages.getString("MysqlIO.47")); //$NON-NLS-1$ + } + + packetLength = (this.packetHeaderBuf[0] & 0xff) + + ((this.packetHeaderBuf[1] & 0xff) << 8) + + ((this.packetHeaderBuf[2] & 0xff) << 16); + + Buffer multiPacket = new Buffer(packetLength); + boolean firstMultiPkt = true; + + while (true) { + if (!firstMultiPkt) { + lengthRead = readFully(this.mysqlInput, + this.packetHeaderBuf, 0, 4); + + if (lengthRead < 4) { + forceClose(); + throw new IOException(Messages.getString( + "MysqlIO.48")); //$NON-NLS-1$ + } + + packetLength = (this.packetHeaderBuf[0] & 0xff) + + ((this.packetHeaderBuf[1] & 0xff) << 8) + + ((this.packetHeaderBuf[2] & 0xff) << 16); + } else { + firstMultiPkt = false; + } + + if (!this.useNewLargePackets && (packetLength == 1)) { + clearInputStream(); + + break; + } else if (packetLength < this.maxThreeBytes) { + byte newPacketSeq = this.packetHeaderBuf[3]; + + if (newPacketSeq != (multiPacketSeq + 1)) { + throw new IOException(Messages.getString( + "MysqlIO.49")); //$NON-NLS-1$ + } + + multiPacketSeq = newPacketSeq; + + // Set the Buffer to it's original state + multiPacket.setPosition(0); + + // Set the new length + multiPacket.setBufLength(packetLength); + + // Read the data from the server + byte[] byteBuf = multiPacket.getByteBuffer(); + int lengthToWrite = packetLength; + + int bytesRead = readFully(this.mysqlInput, byteBuf, + 0, packetLength); + + if (bytesRead != lengthToWrite) { + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, + SQLError.createSQLException(Messages.getString( + "MysqlIO.50") //$NON-NLS-1$ + +lengthToWrite + + Messages.getString("MysqlIO.51") + + bytesRead //$NON-NLS-1$ + +".", getExceptionInterceptor()), getExceptionInterceptor()); //$NON-NLS-1$ + } + + reuse.writeBytesNoNull(byteBuf, 0, lengthToWrite); + + break; // end of multipacket sequence + } + + byte newPacketSeq = this.packetHeaderBuf[3]; + + if (newPacketSeq != (multiPacketSeq + 1)) { + throw new IOException(Messages.getString( + "MysqlIO.53")); //$NON-NLS-1$ + } + + multiPacketSeq = newPacketSeq; + + // Set the Buffer to it's original state + multiPacket.setPosition(0); + + // Set the new length + multiPacket.setBufLength(packetLength); + + // Read the data from the server + byte[] byteBuf = multiPacket.getByteBuffer(); + int lengthToWrite = packetLength; + + int bytesRead = readFully(this.mysqlInput, byteBuf, 0, + packetLength); + + if (bytesRead != lengthToWrite) { + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, + SQLError.createSQLException(Messages.getString( + "MysqlIO.54") //$NON-NLS-1$ + +lengthToWrite + + Messages.getString("MysqlIO.55") //$NON-NLS-1$ + +bytesRead + ".", getExceptionInterceptor()), getExceptionInterceptor()); //$NON-NLS-1$ + } + + reuse.writeBytesNoNull(byteBuf, 0, lengthToWrite); + } + + reuse.setPosition(0); + reuse.setWasMultiPacket(true); + return packetLength; + } + /** * @param multiPacketSeq * @throws CommunicationsException */ private void checkPacketSequencing(byte multiPacketSeq) - throws CommunicationsException { + throws SQLException { if ((multiPacketSeq == -128) && (this.readPacketSequence != 127)) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, new IOException("Packets out of order, expected packet # -128, but received packet # " + - multiPacketSeq)); + multiPacketSeq), getExceptionInterceptor()); } if ((this.readPacketSequence == -1) && (multiPacketSeq != 0)) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, new IOException("Packets out of order, expected packet # -1, but received packet # " + - multiPacketSeq)); + multiPacketSeq), getExceptionInterceptor()); } if ((multiPacketSeq != -128) && (this.readPacketSequence != -1) && (multiPacketSeq != (this.readPacketSequence + 1))) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, new IOException("Packets out of order, expected packet # " + (this.readPacketSequence + 1) + ", but received packet # " + - multiPacketSeq)); + multiPacketSeq), getExceptionInterceptor()); } } void enableMultiQueries() throws SQLException { Buffer buf = getSharedSendPacket(); - + buf.clear(); buf.writeByte((byte)MysqlDefs.COM_SET_OPTION); buf.writeInt(0); - sendCommand(MysqlDefs.COM_SET_OPTION, null, buf, false, null); + sendCommand(MysqlDefs.COM_SET_OPTION, null, buf, false, null, 0); } - + void disableMultiQueries() throws SQLException { Buffer buf = getSharedSendPacket(); - + buf.clear(); buf.writeByte((byte)MysqlDefs.COM_SET_OPTION); buf.writeInt(1); - sendCommand(MysqlDefs.COM_SET_OPTION, null, buf, false, null); + sendCommand(MysqlDefs.COM_SET_OPTION, null, buf, false, null, 0); } - + + /** + * + * @param packet + * @param packetLen length of header + payload + * @throws SQLException + */ private final void send(Buffer packet, int packetLen) throws SQLException { try { - if (packetLen > this.maxAllowedPacket) { + if (this.maxAllowedPacket > 0 && packetLen > this.maxAllowedPacket) { throw new PacketTooBigException(packetLen, this.maxAllowedPacket); } - if (this.connection.getMaintainTimeStats()) { - this.lastPacketSentTimeMs = System.currentTimeMillis(); - } - if ((this.serverMajorVersion >= 4) && - (packetLen >= this.maxThreeBytes)) { - sendSplitPackets(packet); + (packetLen - HEADER_LENGTH >= this.maxThreeBytes || + (this.useCompression && packetLen - HEADER_LENGTH >= this.maxThreeBytes - COMP_HEADER_LENGTH) + )) { + sendSplitPackets(packet, packetLen); + } else { this.packetSequence++; Buffer packetToSend = packet; - packetToSend.setPosition(0); + packetToSend.writeLongInt(packetLen - HEADER_LENGTH); + packetToSend.writeByte(this.packetSequence); if (this.useCompression) { + this.compressedPacketSequence++; int originalPacketLen = packetLen; - packetToSend = compressPacket(packet, 0, packetLen, - HEADER_LENGTH); + packetToSend = compressPacket(packetToSend, 0, packetLen); packetLen = packetToSend.getPosition(); if (this.traceProtocol) { @@ -2725,39 +3944,44 @@ this.connection.getLog().logTrace(traceMessageBuf.toString()); } } else { - packetToSend.writeLongInt(packetLen - HEADER_LENGTH); - packetToSend.writeByte(this.packetSequence); if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); traceMessageBuf.append(Messages.getString("MysqlIO.59")); //$NON-NLS-1$ + traceMessageBuf.append("host: '"); + traceMessageBuf.append(host); + traceMessageBuf.append("' threadId: '"); + traceMessageBuf.append(threadId); + traceMessageBuf.append("'\n"); traceMessageBuf.append(packetToSend.dump(packetLen)); this.connection.getLog().logTrace(traceMessageBuf.toString()); } } - - this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, - packetLen); - this.mysqlOutput.flush(); + this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen); + this.mysqlOutput.flush(); } if (this.enablePacketDebug) { enqueuePacketForDebugging(true, false, packetLen + 5, this.packetHeaderBuf, packet); } - // + // // Don't hold on to large packets // if (packet == this.sharedSendPacket) { reclaimLargeSharedSendPacket(); } + + if (this.connection.getMaintainTimeStats()) { + this.lastPacketSentTimeMs = System.currentTimeMillis(); + } } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } } @@ -2771,34 +3995,38 @@ * * @throws SQLException DOCUMENT ME! */ - private final ResultSet sendFileToServer(Statement callingStatement, + private final ResultSetImpl sendFileToServer(StatementImpl callingStatement, String fileName) throws SQLException { - + + if (this.useCompression) { + this.compressedPacketSequence++; + } + Buffer filePacket = (this.loadFileBufRef == null) ? null - : (Buffer) (this.loadFileBufRef.get()); + : this.loadFileBufRef.get(); int bigPacketLength = Math.min(this.connection.getMaxAllowedPacket() - (HEADER_LENGTH * 3), alignPacketSize(this.connection.getMaxAllowedPacket() - 16, 4096) - (HEADER_LENGTH * 3)); - + int oneMeg = 1024 * 1024; - - int smallerPacketSizeAligned = Math.min(oneMeg - (HEADER_LENGTH * 3), + + int smallerPacketSizeAligned = Math.min(oneMeg - (HEADER_LENGTH * 3), alignPacketSize(oneMeg - 16, 4096) - (HEADER_LENGTH * 3)); - + int packetLength = Math.min(smallerPacketSizeAligned, bigPacketLength); if (filePacket == null) { try { filePacket = new Buffer((packetLength + HEADER_LENGTH)); - this.loadFileBufRef = new SoftReference(filePacket); + this.loadFileBufRef = new SoftReference(filePacket); } catch (OutOfMemoryError oom) { - throw SQLError.createSQLException("Could not allocate packet of " + packetLength - + " bytes required for LOAD DATA LOCAL INFILE operation." + throw SQLError.createSQLException("Could not allocate packet of " + packetLength + + " bytes required for LOAD DATA LOCAL INFILE operation." + " Try increasing max heap allocation for JVM or decreasing server variable " - + "'max_allowed_packet'", SQLError.SQL_STATE_MEMORY_ALLOCATION_FAILURE); - + + "'max_allowed_packet'", SQLError.SQL_STATE_MEMORY_ALLOCATION_FAILURE, getExceptionInterceptor()); + } } @@ -2812,15 +4040,23 @@ try { if (!this.connection.getAllowLoadLocalInfile()) { throw SQLError.createSQLException( - Messages.getString("MysqlIO.LoadDataLocalNotAllowed"), - SQLError.SQL_STATE_GENERAL_ERROR); + Messages.getString("MysqlIO.LoadDataLocalNotAllowed"), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - - if (!this.connection.getAllowUrlInLocalInfile()) { + + InputStream hookedStream = null; + + if (callingStatement != null) { + hookedStream = callingStatement.getLocalInfileInputStream(); + } + + if (hookedStream != null) { + fileIn = new BufferedInputStream(hookedStream); + } else if (!this.connection.getAllowUrlInLocalInfile()) { fileIn = new BufferedInputStream(new FileInputStream(fileName)); } else { // First look for ':' - if (fileName.indexOf(":") != -1) { + if (fileName.indexOf(':') != -1) { try { URL urlFromFileName = new URL(fileName); fileIn = new BufferedInputStream(urlFromFileName.openStream()); @@ -2843,17 +4079,12 @@ send(filePacket, filePacket.getPosition()); } } catch (IOException ioEx) { - StringBuffer messageBuf = new StringBuffer(Messages.getString( - "MysqlIO.60")); //$NON-NLS-1$ + StringBuffer messageBuf = new StringBuffer(Messages.getString("MysqlIO.60")); - if (!this.connection.getParanoid()) { - messageBuf.append("'"); //$NON-NLS-1$ - - if (fileName != null) { - messageBuf.append(fileName); - } - - messageBuf.append("'"); //$NON-NLS-1$ + if (fileName != null && !this.connection.getParanoid()) { + messageBuf.append("'"); + messageBuf.append(fileName); + messageBuf.append("'"); } messageBuf.append(Messages.getString("MysqlIO.63")); //$NON-NLS-1$ @@ -2864,14 +4095,16 @@ } throw SQLError.createSQLException(messageBuf.toString(), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } finally { if (fileIn != null) { try { fileIn.close(); } catch (Exception ex) { - throw SQLError.createSQLException(Messages.getString("MysqlIO.65"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLException sqlEx = SQLError.createSQLException(Messages.getString("MysqlIO.65"), + SQLError.SQL_STATE_GENERAL_ERROR, ex, getExceptionInterceptor()); + + throw sqlEx; } fileIn = null; @@ -2904,7 +4137,7 @@ * @throws CommunicationsException DOCUMENT ME! */ private Buffer checkErrorPacket(int command) throws SQLException { - int statusCode = 0; + //int statusCode = 0; Buffer resultPacket = null; this.serverStatus = 0; @@ -2914,15 +4147,23 @@ // exception chain and let someone higher up decide // what to do (barf, reconnect, etc). resultPacket = reuseAndReadPacket(this.reusablePacket); - statusCode = resultPacket.readByte(); } catch (SQLException sqlEx) { // Don't wrap SQL Exceptions throw sqlEx; } catch (Exception fallThru) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, fallThru); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, fallThru, getExceptionInterceptor()); } + checkErrorPacket(resultPacket); + + return resultPacket; + } + + private void checkErrorPacket(Buffer resultPacket) throws SQLException { + + int statusCode = resultPacket.readByte(); + // Error handling if (statusCode == (byte) 0xff) { String serverErrorMessage; @@ -2933,10 +4174,10 @@ String xOpen = null; - serverErrorMessage = - resultPacket.readString(this.connection.getErrorMessageEncoding()); + serverErrorMessage = + resultPacket.readString(this.connection.getErrorMessageEncoding(), getExceptionInterceptor()); - if (serverErrorMessage.startsWith("#")) { //$NON-NLS-1$ + if (serverErrorMessage.charAt(0) == '#') { //$NON-NLS-1$ // we have an SQLState if (serverErrorMessage.length() > 6) { @@ -2976,42 +4217,40 @@ errorBuf.append("\""); //$NON-NLS-1$ } } - - appendInnodbStatusInformation(xOpen, errorBuf); - + + appendDeadlockStatusInformation(xOpen, errorBuf); + if (xOpen != null && xOpen.startsWith("22")) { - throw new MysqlDataTruncation(errorBuf.toString(), 0, true, false, 0, 0); - } else { - throw SQLError.createSQLException(errorBuf.toString(), xOpen, errno); + throw new MysqlDataTruncation(errorBuf.toString(), 0, true, false, 0, 0, errno); } + throw SQLError.createSQLException(errorBuf.toString(), xOpen, errno, false, getExceptionInterceptor(), this.connection); + } serverErrorMessage = resultPacket.readString( - this.connection.getErrorMessageEncoding()); + this.connection.getErrorMessageEncoding(), getExceptionInterceptor()); clearInputStream(); if (serverErrorMessage.indexOf(Messages.getString("MysqlIO.70")) != -1) { //$NON-NLS-1$ throw SQLError.createSQLException(SQLError.get( SQLError.SQL_STATE_COLUMN_NOT_FOUND) + ", " //$NON-NLS-1$ +serverErrorMessage, SQLError.SQL_STATE_COLUMN_NOT_FOUND, - -1); + -1, false, getExceptionInterceptor(), this.connection); } StringBuffer errorBuf = new StringBuffer(Messages.getString( "MysqlIO.72")); //$NON-NLS-1$ errorBuf.append(serverErrorMessage); errorBuf.append("\""); //$NON-NLS-1$ - + throw SQLError.createSQLException(SQLError.get( SQLError.SQL_STATE_GENERAL_ERROR) + ", " //$NON-NLS-1$ - +errorBuf.toString(), SQLError.SQL_STATE_GENERAL_ERROR, -1); + +errorBuf.toString(), SQLError.SQL_STATE_GENERAL_ERROR, -1, false, getExceptionInterceptor(), this.connection); } - - return resultPacket; } - private void appendInnodbStatusInformation(String xOpen, + private void appendDeadlockStatusInformation(String xOpen, StringBuffer errorBuf) throws SQLException { if (this.connection.getIncludeInnodbStatusInDeadlockExceptions() && xOpen != null @@ -3022,17 +4261,20 @@ try { rs = sqlQueryDirect(null, "SHOW ENGINE INNODB STATUS", this.connection.getEncoding(), null, -1, - this.connection, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, false, this.connection - .getCatalog(), true); + .getCatalog(), null); + if (rs.next()) { errorBuf.append("\n\n"); - errorBuf.append(rs.getString(1)); + errorBuf.append(rs.getString("Status")); } else { + errorBuf.append("\n\n"); errorBuf.append(Messages .getString("MysqlIO.NoInnoDBStatusFound")); } } catch (Exception ex) { + errorBuf.append("\n\n"); errorBuf.append(Messages .getString("MysqlIO.InnoDBStatusFailed")); errorBuf.append("\n\n"); @@ -3043,126 +4285,164 @@ } } } + + if (this.connection.getIncludeThreadDumpInDeadlockExceptions()) { + errorBuf.append("\n\n*** Java threads running at time of deadlock ***\n\n"); + + ThreadMXBean threadMBean = ManagementFactory.getThreadMXBean(); + long[] threadIds = threadMBean.getAllThreadIds(); + + ThreadInfo[] threads = threadMBean.getThreadInfo(threadIds, + Integer.MAX_VALUE); + List activeThreads = new ArrayList(); + + for (ThreadInfo info : threads) { + if (info != null) { + activeThreads.add(info); + } + } + + for (ThreadInfo threadInfo : activeThreads) { + // "Thread-60" daemon prio=1 tid=0x093569c0 nid=0x1b99 in + // Object.wait() + + errorBuf.append('"'); + errorBuf.append(threadInfo.getThreadName()); + errorBuf.append("\" tid="); + errorBuf.append(threadInfo.getThreadId()); + errorBuf.append(" "); + errorBuf.append(threadInfo.getThreadState()); + + if (threadInfo.getLockName() != null) { + errorBuf.append(" on lock=" + threadInfo.getLockName()); + } + if (threadInfo.isSuspended()) { + errorBuf.append(" (suspended)"); + } + if (threadInfo.isInNative()) { + errorBuf.append(" (running in native)"); + } + + StackTraceElement[] stackTrace = threadInfo.getStackTrace(); + + if (stackTrace.length > 0) { + errorBuf.append(" in "); + errorBuf.append(stackTrace[0].getClassName()); + errorBuf.append("."); + errorBuf.append(stackTrace[0].getMethodName()); + errorBuf.append("()"); + } + + errorBuf.append("\n"); + + if (threadInfo.getLockOwnerName() != null) { + errorBuf.append("\t owned by " + threadInfo.getLockOwnerName() + + " Id=" + threadInfo.getLockOwnerId()); + errorBuf.append("\n"); + } + + for (int j = 0; j < stackTrace.length; j++) { + StackTraceElement ste = stackTrace[j]; + errorBuf.append("\tat " + ste.toString()); + errorBuf.append("\n"); + } + } + } } /** - * Sends a large packet to the server as a series of smaller packets - * - * @param packet - * DOCUMENT ME! - * - * @throws SQLException - * DOCUMENT ME! - * @throws CommunicationsException - * DOCUMENT ME! - */ - private final void sendSplitPackets(Buffer packet) + * Sends a large packet to the server as a series of smaller packets + * + * @param packet DOCUMENT ME! + * + * @throws SQLException DOCUMENT ME! + * @throws CommunicationsException DOCUMENT ME! + */ + private final void sendSplitPackets(Buffer packet, int packetLen) throws SQLException { try { - // - // Big packets are handled by splitting them in packets of MAX_THREE_BYTES - // length. The last packet is always a packet that is < MAX_THREE_BYTES. - // (The last packet may even have a length of 0) - // - // - // NB: Guarded by execSQL. If the driver changes architecture, this - // will need to be synchronized in some other way - // - Buffer headerPacket = (this.splitBufRef == null) ? null - : (Buffer) (this.splitBufRef.get()); + Buffer packetToSend = (this.splitBufRef == null) ? null : this.splitBufRef.get(); + Buffer toCompress = (!this.useCompression || this.compressBufRef == null) ? null : this.compressBufRef.get(); // // Store this packet in a soft reference...It can be re-used if not GC'd (so clients // that use it frequently won't have to re-alloc the 16M buffer), but we don't // penalize infrequent users of large packets by keeping 16M allocated all of the time // - if (headerPacket == null) { - headerPacket = new Buffer((this.maxThreeBytes + - HEADER_LENGTH)); - this.splitBufRef = new SoftReference(headerPacket); + if (packetToSend == null) { + packetToSend = new Buffer((this.maxThreeBytes + HEADER_LENGTH)); + this.splitBufRef = new SoftReference(packetToSend); } + if (this.useCompression) { + int cbuflen = packetLen + ((packetLen / this.maxThreeBytes) + 1) * HEADER_LENGTH; + if (toCompress == null) { + toCompress = new Buffer(cbuflen); + } else if (toCompress.getBufLength() < cbuflen) { + toCompress.setPosition(toCompress.getBufLength()); + toCompress.ensureCapacity(cbuflen - toCompress.getBufLength()); + } + } - int len = packet.getPosition(); + int len = packetLen - HEADER_LENGTH; // payload length left int splitSize = this.maxThreeBytes; int originalPacketPos = HEADER_LENGTH; byte[] origPacketBytes = packet.getByteBuffer(); - byte[] headerPacketBytes = headerPacket.getByteBuffer(); - while (len >= this.maxThreeBytes) { + int toCompressPosition = 0; + + // split to MySQL packets + while (len >= 0) { this.packetSequence++; - headerPacket.setPosition(0); - headerPacket.writeLongInt(splitSize); - - headerPacket.writeByte(this.packetSequence); - System.arraycopy(origPacketBytes, originalPacketPos, - headerPacketBytes, 4, splitSize); - - int packetLen = splitSize + HEADER_LENGTH; - - // - // Swap a compressed packet in, if we're using - // compression... - // - if (!this.useCompression) { - this.mysqlOutput.write(headerPacketBytes, 0, - splitSize + HEADER_LENGTH); - this.mysqlOutput.flush(); + if (len < splitSize) { + splitSize = len; + } + + packetToSend.setPosition(0); + packetToSend.writeLongInt(splitSize); + packetToSend.writeByte(this.packetSequence); + if (len > 0) { + System.arraycopy(origPacketBytes, originalPacketPos, packetToSend.getByteBuffer(), HEADER_LENGTH, splitSize); + } + + if (this.useCompression) { + System.arraycopy(packetToSend.getByteBuffer(), 0, toCompress.getByteBuffer(), toCompressPosition, HEADER_LENGTH + splitSize); + toCompressPosition += HEADER_LENGTH + splitSize; } else { - Buffer packetToSend; - - headerPacket.setPosition(0); - packetToSend = compressPacket(headerPacket, HEADER_LENGTH, - splitSize, HEADER_LENGTH); - packetLen = packetToSend.getPosition(); - - this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, - packetLen); + this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, HEADER_LENGTH + splitSize); this.mysqlOutput.flush(); } originalPacketPos += splitSize; - len -= splitSize; + len -= this.maxThreeBytes; + } - // - // Write last packet - // - headerPacket.clear(); - headerPacket.setPosition(0); - headerPacket.writeLongInt(len - HEADER_LENGTH); - this.packetSequence++; - headerPacket.writeByte(this.packetSequence); + // split to compressed packets + if (this.useCompression) { + len = toCompressPosition; + toCompressPosition = 0; + splitSize = this.maxThreeBytes- COMP_HEADER_LENGTH; + while (len >= 0) { + this.compressedPacketSequence++; - if (len != 0) { - System.arraycopy(origPacketBytes, originalPacketPos, - headerPacketBytes, 4, len - HEADER_LENGTH); - } + if (len < splitSize) { + splitSize = len; + } - int packetLen = len - HEADER_LENGTH; + Buffer compressedPacketToSend = compressPacket(toCompress, toCompressPosition, splitSize); + packetLen = compressedPacketToSend.getPosition(); + this.mysqlOutput.write(compressedPacketToSend.getByteBuffer(), 0, packetLen); + this.mysqlOutput.flush(); - // - // Swap a compressed packet in, if we're using - // compression... - // - if (!this.useCompression) { - this.mysqlOutput.write(headerPacket.getByteBuffer(), 0, len); - this.mysqlOutput.flush(); - } else { - Buffer packetToSend; - headerPacket.setPosition(0); - packetToSend = compressPacket(headerPacket, HEADER_LENGTH, - packetLen, HEADER_LENGTH); - packetLen = packetToSend.getPosition(); - - this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, - packetLen); - this.mysqlOutput.flush(); + toCompressPosition += splitSize; + len -= (this.maxThreeBytes-COMP_HEADER_LENGTH); + } } } catch (IOException ioEx) { - throw new CommunicationsException(this.connection, - this.lastPacketSentTimeMs, ioEx); + throw SQLError.createCommunicationsException(this.connection, + this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx, getExceptionInterceptor()); } } @@ -3176,12 +4456,12 @@ boolean hadWarnings() { return this.hadWarnings; } - + void scanForAndThrowDataTruncation() throws SQLException { if ((this.streamingData == null) && versionMeetsMinimum(4, 1, 0) && this.connection.getJdbcCompliantTruncation() && this.warningCount > 0) { - SQLError.convertShowWarningsToSQLWarnings(this.connection, - this.warningCount, true); + SQLError.convertShowWarningsToSQLWarnings(this.connection, + this.warningCount, true); } } @@ -3229,18 +4509,18 @@ } // User/Password data - packet.writeString(user, "Cp1252", this.connection); + packet.writeString(user, CODE_PAGE_1252, this.connection); if (password.length() != 0) { /* Prepare false scramble */ - packet.writeString(FALSE_SCRAMBLE, "Cp1252", this.connection); + packet.writeString(FALSE_SCRAMBLE, CODE_PAGE_1252, this.connection); } else { /* For empty password*/ - packet.writeString("", "Cp1252", this.connection); //$NON-NLS-1$ + packet.writeString("", CODE_PAGE_1252, this.connection); //$NON-NLS-1$ } if (this.useConnectWithDb) { - packet.writeString(database, "Cp1252", this.connection); + packet.writeString(database, CODE_PAGE_1252, this.connection); } send(packet, packet.getPosition()); @@ -3279,11 +4559,11 @@ byte[] mysqlScrambleBuff = new byte[20]; /* Decypt and store scramble 4 = hash for stage2 */ - Security.passwordCrypt(packetDataAfterSalt, + Security.xorString(packetDataAfterSalt, mysqlScrambleBuff, passwordHash, 20); /* Encode scramble with password. Recycle buffer */ - Security.passwordCrypt(mysqlScrambleBuff, buff, buff, 20); + Security.xorString(mysqlScrambleBuff, buff, buff, 20); Buffer packet2 = new Buffer(25); packet2.writeBytesNoNull(buff); @@ -3294,7 +4574,7 @@ } catch (NoSuchAlgorithmException nse) { throw SQLError.createSQLException(Messages.getString("MysqlIO.91") //$NON-NLS-1$ +Messages.getString("MysqlIO.92"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } else { try { @@ -3310,22 +4590,22 @@ byte[] mysqlScrambleBuff = new byte[20]; /* Decypt and store scramble 4 = hash for stage2 */ - Security.passwordCrypt(netReadPos4, mysqlScrambleBuff, + Security.xorString(netReadPos4, mysqlScrambleBuff, passwordHash, 20); /* Finally scramble decoded scramble with password */ - String scrambledPassword = Util.scramble(new String( + String scrambledPassword = Util.scramble(StringUtils.toString( mysqlScrambleBuff), password); Buffer packet2 = new Buffer(packLength); - packet2.writeString(scrambledPassword, "Cp1252", this.connection); + packet2.writeString(scrambledPassword, CODE_PAGE_1252, this.connection); this.packetSequence++; send(packet2, 24); } catch (NoSuchAlgorithmException nse) { throw SQLError.createSQLException(Messages.getString("MysqlIO.93") //$NON-NLS-1$ +Messages.getString("MysqlIO.94"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } } @@ -3375,10 +4655,10 @@ packet.writeLong(this.clientParam); packet.writeLong(this.maxThreeBytes); - // charset, JDBC will connect as 'latin1', + // charset, JDBC will connect as 'utf8', // and use 'SET NAMES' to change to the desired // charset after the connection is established. - packet.writeByte((byte) 8); + packet.writeByte((byte) UTF8_CHARSET_INDEX); // Set of bytes reserved for future use. packet.writeBytesNoNull(new byte[23]); @@ -3393,26 +4673,51 @@ } // User/Password data - packet.writeString(user); + packet.writeString(user, "utf-8", this.connection); if (password.length() != 0) { packet.writeByte((byte) 0x14); try { - packet.writeBytesNoNull(Security.scramble411(password, this.seed)); + packet.writeBytesNoNull(Security.scramble411(password, this.seed, + this.connection.getPasswordCharacterEncoding())); } catch (NoSuchAlgorithmException nse) { throw SQLError.createSQLException(Messages.getString("MysqlIO.95") //$NON-NLS-1$ +Messages.getString("MysqlIO.96"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); - } + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } catch (UnsupportedEncodingException e) { + throw SQLError.createSQLException(Messages.getString("MysqlIO.95") //$NON-NLS-1$ + +Messages.getString("MysqlIO.96"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } } else { /* For empty password*/ packet.writeByte((byte) 0); } if (this.useConnectWithDb) { - packet.writeString(database); + packet.writeString(database, "utf-8", this.connection); + } else { + /* For empty database*/ + packet.writeByte((byte) 0); } + + if ((this.serverCapabilities & CLIENT_PROTOCOL_41) != 0) { + // charset (2 bytes low-endian) + String mysqlEncodingName = this.connection.getServerCharacterEncoding(); + if ("ucs2".equalsIgnoreCase(mysqlEncodingName) || + "utf16".equalsIgnoreCase(mysqlEncodingName) || + "utf16le".equalsIgnoreCase(mysqlEncodingName) || + "uft32".equalsIgnoreCase(mysqlEncodingName)) { + packet.writeByte((byte) UTF8_CHARSET_INDEX); + packet.writeByte((byte) 0); + } + } + + // connection attributes + if ((this.serverCapabilities & CLIENT_CONNECT_ATTRS) != 0) { + sendConnectionAttributes(packet, "utf-8", this.connection); + } send(packet, packet.getPosition()); @@ -3448,110 +4753,103 @@ * * @throws SQLException DOCUMENT ME! */ - private final Object[] unpackBinaryResultSetRow(Field[] fields, + private final ResultSetRow unpackBinaryResultSetRow(Field[] fields, Buffer binaryData, int resultSetConcurrency) throws SQLException { int numFields = fields.length; - Object[] unpackedRowData = new Object[numFields]; + byte[][] unpackedRowData = new byte[numFields][]; // // Unpack the null bitmask, first // - /* Reserve place for null-marker bytes */ int nullCount = (numFields + 9) / 8; - - byte[] nullBitMask = new byte[nullCount]; - - for (int i = 0; i < nullCount; i++) { - nullBitMask[i] = binaryData.readByte(); - } - - int nullMaskPos = 0; + int nullMaskPos = binaryData.getPosition(); + binaryData.setPosition(nullMaskPos + nullCount); int bit = 4; // first two bits are reserved for future use - + // // TODO: Benchmark if moving check for updatable result // sets out of loop is worthwhile? // - + for (int i = 0; i < numFields; i++) { - if ((nullBitMask[nullMaskPos] & bit) != 0) { + if ((binaryData.readByte(nullMaskPos) & bit) != 0) { unpackedRowData[i] = null; } else { - if (resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) { - extractNativeEncodedColumn(binaryData, fields, i, + if (resultSetConcurrency != ResultSetInternalMethods.CONCUR_UPDATABLE) { + extractNativeEncodedColumn(binaryData, fields, i, unpackedRowData); } else { - unpackNativeEncodedColumn(binaryData, fields, i, + unpackNativeEncodedColumn(binaryData, fields, i, unpackedRowData); - } + } } - + if (((bit <<= 1) & 255) == 0) { bit = 1; /* To next byte */ nullMaskPos++; } } - return unpackedRowData; + return new ByteArrayRow(unpackedRowData, getExceptionInterceptor()); } - - private final void extractNativeEncodedColumn(Buffer binaryData, - Field[] fields, int columnIndex, Object[] unpackedRowData) throws SQLException { + + private final void extractNativeEncodedColumn(Buffer binaryData, + Field[] fields, int columnIndex, byte[][] unpackedRowData) throws SQLException { Field curField = fields[columnIndex]; - + switch (curField.getMysqlType()) { case MysqlDefs.FIELD_TYPE_NULL: break; // for dummy binds - + case MysqlDefs.FIELD_TYPE_TINY: unpackedRowData[columnIndex] = new byte[] {binaryData.readByte()}; break; - + case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_YEAR: - + unpackedRowData[columnIndex] = binaryData.getBytes(2); break; case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_INT24: - + unpackedRowData[columnIndex] = binaryData.getBytes(4); break; case MysqlDefs.FIELD_TYPE_LONGLONG: unpackedRowData[columnIndex] = binaryData.getBytes(8); break; case MysqlDefs.FIELD_TYPE_FLOAT: - + unpackedRowData[columnIndex] = binaryData.getBytes(4); - break; + break; case MysqlDefs.FIELD_TYPE_DOUBLE: - + unpackedRowData[columnIndex] = binaryData.getBytes(8); break; case MysqlDefs.FIELD_TYPE_TIME: - + int length = (int) binaryData.readFieldLength(); - + unpackedRowData[columnIndex] = binaryData.getBytes(length); break; case MysqlDefs.FIELD_TYPE_DATE: - + length = (int) binaryData.readFieldLength(); - + unpackedRowData[columnIndex] = binaryData.getBytes(length); break; case MysqlDefs.FIELD_TYPE_DATETIME: case MysqlDefs.FIELD_TYPE_TIMESTAMP: length = (int) binaryData.readFieldLength(); - + unpackedRowData[columnIndex] = binaryData.getBytes(length); break; case MysqlDefs.FIELD_TYPE_TINY_BLOB: @@ -3565,346 +4863,346 @@ case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: case MysqlDefs.FIELD_TYPE_GEOMETRY: unpackedRowData[columnIndex] = binaryData.readLenByteArray(0); - + break; case MysqlDefs.FIELD_TYPE_BIT: unpackedRowData[columnIndex] = binaryData.readLenByteArray(0); - + break; default: throw SQLError.createSQLException(Messages.getString("MysqlIO.97") //$NON-NLS-1$ +curField.getMysqlType() + Messages.getString("MysqlIO.98") + columnIndex + Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$ + fields.length + Messages.getString("MysqlIO.100"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } - private final void unpackNativeEncodedColumn(Buffer binaryData, - Field[] fields, int columnIndex, Object[] unpackedRowData) + private final void unpackNativeEncodedColumn(Buffer binaryData, + Field[] fields, int columnIndex, byte[][] unpackedRowData) throws SQLException { Field curField = fields[columnIndex]; - + switch (curField.getMysqlType()) { case MysqlDefs.FIELD_TYPE_NULL: break; // for dummy binds - + case MysqlDefs.FIELD_TYPE_TINY: - + byte tinyVal = binaryData.readByte(); - - if (!curField.isUnsigned()) { - unpackedRowData[columnIndex] = String.valueOf(tinyVal) - .getBytes(); + + if (!curField.isUnsigned()) { + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(tinyVal)); } else { short unsignedTinyVal = (short) (tinyVal & 0xff); - - unpackedRowData[columnIndex] = String.valueOf(unsignedTinyVal) - .getBytes(); + + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(unsignedTinyVal)); } - + break; - + case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_YEAR: - + short shortVal = (short) binaryData.readInt(); - + if (!curField.isUnsigned()) { - unpackedRowData[columnIndex] = String.valueOf(shortVal) - .getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(shortVal)); } else { int unsignedShortVal = shortVal & 0xffff; - unpackedRowData[columnIndex] = String.valueOf(unsignedShortVal) - .getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(unsignedShortVal)); } - + break; - + case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_INT24: - + int intVal = (int) binaryData.readLong(); - + if (!curField.isUnsigned()) { - unpackedRowData[columnIndex] = String.valueOf(intVal) - .getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(intVal)); } else { long longVal = intVal & 0xffffffffL; - unpackedRowData[columnIndex] = String.valueOf(longVal) - .getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(longVal)); } - + break; - + case MysqlDefs.FIELD_TYPE_LONGLONG: - + long longVal = binaryData.readLongLong(); - + if (!curField.isUnsigned()) { - unpackedRowData[columnIndex] = String.valueOf(longVal) - .getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(longVal)); } else { - BigInteger asBigInteger = ResultSet.convertLongToUlong(longVal); + BigInteger asBigInteger = ResultSetImpl.convertLongToUlong(longVal); - unpackedRowData[columnIndex] = asBigInteger.toString() - .getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + asBigInteger.toString()); } - + break; - + case MysqlDefs.FIELD_TYPE_FLOAT: - + float floatVal = Float.intBitsToFloat(binaryData.readIntAsLong()); - - unpackedRowData[columnIndex] = String.valueOf(floatVal).getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(floatVal)); + break; - + case MysqlDefs.FIELD_TYPE_DOUBLE: - + double doubleVal = Double.longBitsToDouble(binaryData.readLongLong()); - unpackedRowData[columnIndex] = String.valueOf(doubleVal).getBytes(); + unpackedRowData[columnIndex] = StringUtils.getBytes( + String.valueOf(doubleVal)); break; - + case MysqlDefs.FIELD_TYPE_TIME: - + int length = (int) binaryData.readFieldLength(); - + int hour = 0; int minute = 0; int seconds = 0; - + if (length != 0) { binaryData.readByte(); // skip tm->neg binaryData.readLong(); // skip daysPart hour = binaryData.readByte(); minute = binaryData.readByte(); seconds = binaryData.readByte(); - + if (length > 8) { binaryData.readLong(); // ignore 'secondsPart' } } - - + + byte[] timeAsBytes = new byte[8]; - + timeAsBytes[0] = (byte) Character.forDigit(hour / 10, 10); timeAsBytes[1] = (byte) Character.forDigit(hour % 10, 10); - + timeAsBytes[2] = (byte) ':'; - + timeAsBytes[3] = (byte) Character.forDigit(minute / 10, 10); timeAsBytes[4] = (byte) Character.forDigit(minute % 10, 10); - + timeAsBytes[5] = (byte) ':'; - + timeAsBytes[6] = (byte) Character.forDigit(seconds / 10, 10); timeAsBytes[7] = (byte) Character.forDigit(seconds % 10, 10); - + unpackedRowData[columnIndex] = timeAsBytes; - - + + break; - + case MysqlDefs.FIELD_TYPE_DATE: length = (int) binaryData.readFieldLength(); - + int year = 0; int month = 0; int day = 0; - + hour = 0; minute = 0; seconds = 0; - + if (length != 0) { year = binaryData.readInt(); month = binaryData.readByte(); day = binaryData.readByte(); } - + if ((year == 0) && (month == 0) && (day == 0)) { - if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( this.connection.getZeroDateTimeBehavior())) { unpackedRowData[columnIndex] = null; - + break; - } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( this.connection.getZeroDateTimeBehavior())) { throw SQLError.createSQLException("Value '0000-00-00' can not be represented as java.sql.Date", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - + year = 1; month = 1; day = 1; } - - + + byte[] dateAsBytes = new byte[10]; - + dateAsBytes[0] = (byte) Character.forDigit(year / 1000, 10); - + int after1000 = year % 1000; - + dateAsBytes[1] = (byte) Character.forDigit(after1000 / 100, 10); - + int after100 = after1000 % 100; - + dateAsBytes[2] = (byte) Character.forDigit(after100 / 10, 10); dateAsBytes[3] = (byte) Character.forDigit(after100 % 10, 10); - + dateAsBytes[4] = (byte) '-'; - + dateAsBytes[5] = (byte) Character.forDigit(month / 10, 10); dateAsBytes[6] = (byte) Character.forDigit(month % 10, 10); - + dateAsBytes[7] = (byte) '-'; - + dateAsBytes[8] = (byte) Character.forDigit(day / 10, 10); dateAsBytes[9] = (byte) Character.forDigit(day % 10, 10); - + unpackedRowData[columnIndex] = dateAsBytes; - - + + break; - + case MysqlDefs.FIELD_TYPE_DATETIME: case MysqlDefs.FIELD_TYPE_TIMESTAMP: length = (int) binaryData.readFieldLength(); - + year = 0; month = 0; day = 0; - + hour = 0; minute = 0; seconds = 0; - + int nanos = 0; - + if (length != 0) { year = binaryData.readInt(); month = binaryData.readByte(); day = binaryData.readByte(); - + if (length > 4) { hour = binaryData.readByte(); minute = binaryData.readByte(); seconds = binaryData.readByte(); } - + //if (length > 7) { // nanos = (int)binaryData.readLong(); //} } - + if ((year == 0) && (month == 0) && (day == 0)) { - if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL.equals( this.connection.getZeroDateTimeBehavior())) { unpackedRowData[columnIndex] = null; - + break; - } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION.equals( this.connection.getZeroDateTimeBehavior())) { throw SQLError.createSQLException("Value '0000-00-00' can not be represented as java.sql.Timestamp", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - + year = 1; month = 1; day = 1; } - - + + int stringLength = 19; - - byte[] nanosAsBytes = Integer.toString(nanos).getBytes(); - + + byte[] nanosAsBytes = StringUtils.getBytes(Integer.toString(nanos)); + stringLength += (1 + nanosAsBytes.length); // '.' + # of digits - + byte[] datetimeAsBytes = new byte[stringLength]; - + datetimeAsBytes[0] = (byte) Character.forDigit(year / 1000, 10); - + after1000 = year % 1000; - + datetimeAsBytes[1] = (byte) Character.forDigit(after1000 / 100, 10); - + after100 = after1000 % 100; - + datetimeAsBytes[2] = (byte) Character.forDigit(after100 / 10, 10); datetimeAsBytes[3] = (byte) Character.forDigit(after100 % 10, 10); - + datetimeAsBytes[4] = (byte) '-'; - + datetimeAsBytes[5] = (byte) Character.forDigit(month / 10, 10); datetimeAsBytes[6] = (byte) Character.forDigit(month % 10, 10); - + datetimeAsBytes[7] = (byte) '-'; - + datetimeAsBytes[8] = (byte) Character.forDigit(day / 10, 10); datetimeAsBytes[9] = (byte) Character.forDigit(day % 10, 10); - + datetimeAsBytes[10] = (byte) ' '; - + datetimeAsBytes[11] = (byte) Character.forDigit(hour / 10, 10); datetimeAsBytes[12] = (byte) Character.forDigit(hour % 10, 10); - + datetimeAsBytes[13] = (byte) ':'; - + datetimeAsBytes[14] = (byte) Character.forDigit(minute / 10, 10); datetimeAsBytes[15] = (byte) Character.forDigit(minute % 10, 10); - + datetimeAsBytes[16] = (byte) ':'; - + datetimeAsBytes[17] = (byte) Character.forDigit(seconds / 10, 10); datetimeAsBytes[18] = (byte) Character.forDigit(seconds % 10, 10); - + datetimeAsBytes[19] = (byte) '.'; + + final int nanosOffset = 20; + + System.arraycopy(nanosAsBytes, 0, datetimeAsBytes, nanosOffset, nanosAsBytes.length); - int nanosOffset = 20; - - for (int j = 0; j < nanosAsBytes.length; j++) { - datetimeAsBytes[nanosOffset + j] = nanosAsBytes[j]; - } - unpackedRowData[columnIndex] = datetimeAsBytes; - - + + break; - + case MysqlDefs.FIELD_TYPE_TINY_BLOB: case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: case MysqlDefs.FIELD_TYPE_LONG_BLOB: @@ -3916,32 +5214,20 @@ case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: case MysqlDefs.FIELD_TYPE_BIT: unpackedRowData[columnIndex] = binaryData.readLenByteArray(0); - + break; - + default: throw SQLError.createSQLException(Messages.getString("MysqlIO.97") //$NON-NLS-1$ +curField.getMysqlType() + Messages.getString("MysqlIO.98") + columnIndex + Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$ + fields.length + Messages.getString("MysqlIO.100"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } } - + /** - * Optimization to only use one calendar per-session, or calculate it - * for each call, depending on user configuration - */ - private Calendar getCalendarInstanceForSessionOrNew() { - if (this.connection.getDynamicCalendars()) { - return Calendar.getInstance(); - } else { - return this.sessionCalendar; - } - } - - /** * Negotiates the SSL communications channel used when connecting * to a MySQL server that understands SSL. * @@ -3954,17 +5240,14 @@ */ private void negotiateSSLConnection(String user, String password, String database, int packLength) - throws SQLException, CommunicationsException { + throws SQLException { if (!ExportControlled.enabled()) { throw new ConnectionFeatureNotAvailableException(this.connection, this.lastPacketSentTimeMs, null); } - boolean doSecureAuth = false; - if ((this.serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) { this.clientParam |= CLIENT_SECURE_CONNECTION; - doSecureAuth = true; } this.clientParam |= CLIENT_SSL; @@ -3973,78 +5256,55 @@ if (this.use41Extensions) { packet.writeLong(this.clientParam); + packet.writeLong(this.maxThreeBytes); + int charsetIndex = 0; + if (this.connection.getEncoding() != null) { + charsetIndex = CharsetMapping.getCharsetIndexForMysqlEncodingName(CharsetMapping.getMysqlEncodingForJavaEncoding(this.connection.getEncoding(), this.connection)); + } + packet.writeByte(charsetIndex == 0 ? (byte) UTF8_CHARSET_INDEX : (byte) charsetIndex); + packet.writeBytesNoNull(new byte[23]); // Set of bytes reserved for future use. } else { packet.writeInt((int) this.clientParam); } send(packet, packet.getPosition()); ExportControlled.transformSocketToSSLSocket(this); - - packet.clear(); - - if (doSecureAuth) { - if (versionMeetsMinimum(4, 1, 1)) { - secureAuth411(null, packLength, user, password, database, true); - } else { - secureAuth411(null, packLength, user, password, database, true); - } - } else { - if (this.use41Extensions) { - packet.writeLong(this.clientParam); - packet.writeLong(this.maxThreeBytes); - } else { - packet.writeInt((int) this.clientParam); - packet.writeLongInt(this.maxThreeBytes); - } - - // User/Password data - packet.writeString(user); - - if (this.protocolVersion > 9) { - packet.writeString(Util.newCrypt(password, this.seed)); - } else { - packet.writeString(Util.oldCrypt(password, this.seed)); - } - - if (((this.serverCapabilities & CLIENT_CONNECT_WITH_DB) != 0) && - (database != null) && (database.length() > 0)) { - packet.writeString(database); - } - - send(packet, packet.getPosition()); - } } + public boolean isSSLEstablished() { + return ExportControlled.enabled() && ExportControlled.isSSLEstablished(this); + } + protected int getServerStatus() { return this.serverStatus; } - protected List fetchRowsViaCursor(List fetchedRows, long statementId, - Field[] columnTypes, int fetchSize) throws SQLException { - + protected List fetchRowsViaCursor(List fetchedRows, long statementId, + Field[] columnTypes, int fetchSize, boolean useBufferRowExplicit) throws SQLException { + if (fetchedRows == null) { - fetchedRows = new ArrayList(fetchSize); + fetchedRows = new ArrayList(fetchSize); } else { fetchedRows.clear(); } - + this.sharedSendPacket.clear(); - + this.sharedSendPacket.writeByte((byte) MysqlDefs.COM_FETCH); this.sharedSendPacket.writeLong(statementId); this.sharedSendPacket.writeLong(fetchSize); - + sendCommand(MysqlDefs.COM_FETCH, null, this.sharedSendPacket, true, - null); - - Object[] row = null; - + null, 0); + + ResultSetRow row = null; + while ((row = nextRow(columnTypes, columnTypes.length, true, - ResultSet.CONCUR_READ_ONLY)) != null) { + ResultSet.CONCUR_READ_ONLY, false, useBufferRowExplicit, false, null)) != null) { fetchedRows.add(row); } - + return fetchedRows; } @@ -4063,4 +5323,45 @@ protected String getQueryTimingUnits() { return this.queryTimingUnits; } + + protected int getCommandCount() { + return this.commandCount; + } + + private void checkTransactionState(int oldStatus) throws SQLException { + boolean previouslyInTrans = ((oldStatus & SERVER_STATUS_IN_TRANS) != 0); + boolean currentlyInTrans = ((this.serverStatus & SERVER_STATUS_IN_TRANS) != 0); + + if (previouslyInTrans && !currentlyInTrans) { + this.connection.transactionCompleted(); + } else if (!previouslyInTrans && currentlyInTrans) { + this.connection.transactionBegun(); + } + } + + protected void setStatementInterceptors(List statementInterceptors) { + this.statementInterceptors = statementInterceptors.isEmpty() ? null : statementInterceptors; + } + + protected ExceptionInterceptor getExceptionInterceptor() { + return this.exceptionInterceptor; + } + + protected void setSocketTimeout(int milliseconds) throws SQLException { + try { + mysqlConnection.setSoTimeout(milliseconds); + } catch (SocketException e) { + SQLException sqlEx = SQLError.createSQLException("Invalid socket timeout value or state", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } + } + + protected void releaseResources() { + if (this.deflater != null) { + this.deflater.end(); + this.deflater = null; + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlParameterMetadata.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlParameterMetadata.java (.../MysqlParameterMetadata.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlParameterMetadata.java (.../MysqlParameterMetadata.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,25 +1,25 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc; @@ -29,134 +29,186 @@ public class MysqlParameterMetadata implements ParameterMetaData { boolean returnSimpleMetadata = false; + ResultSetMetaData metadata = null; + int parameterCount = 0; + + private ExceptionInterceptor exceptionInterceptor; - - MysqlParameterMetadata(Field[] fieldInfo, int parameterCount) { - this.metadata = new ResultSetMetaData(fieldInfo, false); - + MysqlParameterMetadata(Field[] fieldInfo, int parameterCount, ExceptionInterceptor exceptionInterceptor) { + this.metadata = new ResultSetMetaData(fieldInfo, false, true, exceptionInterceptor); + this.parameterCount = parameterCount; + this.exceptionInterceptor = exceptionInterceptor; } - + /** - * Used for "fake" basic metadata for client-side prepared statements - * when we don't know the parameter types. + * Used for "fake" basic metadata for client-side prepared statements when + * we don't know the parameter types. * * @param parameterCount */ MysqlParameterMetadata(int count) { this.parameterCount = count; this.returnSimpleMetadata = true; } - + public int getParameterCount() throws SQLException { return this.parameterCount; } public int isNullable(int arg0) throws SQLException { checkAvailable(); - + return this.metadata.isNullable(arg0); } private void checkAvailable() throws SQLException { if (this.metadata == null || this.metadata.fields == null) { throw SQLError.createSQLException( - "Parameter metadata not available for the given statement", - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); + "Parameter metadata not available for the given statement", + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, this.exceptionInterceptor); } } public boolean isSigned(int arg0) throws SQLException { if (this.returnSimpleMetadata) { checkBounds(arg0); - + return false; } - + checkAvailable(); - + return (this.metadata.isSigned(arg0)); } public int getPrecision(int arg0) throws SQLException { if (this.returnSimpleMetadata) { checkBounds(arg0); - + return 0; } - + checkAvailable(); - + return (this.metadata.getPrecision(arg0)); } public int getScale(int arg0) throws SQLException { if (this.returnSimpleMetadata) { checkBounds(arg0); - + return 0; } - + checkAvailable(); - + return (this.metadata.getScale(arg0)); } public int getParameterType(int arg0) throws SQLException { if (this.returnSimpleMetadata) { checkBounds(arg0); - + return Types.VARCHAR; } - + checkAvailable(); - + return (this.metadata.getColumnType(arg0)); } public String getParameterTypeName(int arg0) throws SQLException { if (this.returnSimpleMetadata) { checkBounds(arg0); - + return "VARCHAR"; } - + checkAvailable(); - + return (this.metadata.getColumnTypeName(arg0)); } public String getParameterClassName(int arg0) throws SQLException { if (this.returnSimpleMetadata) { checkBounds(arg0); - + return "java.lang.String"; } - + checkAvailable(); - + return (this.metadata.getColumnClassName(arg0)); } public int getParameterMode(int arg0) throws SQLException { return parameterModeIn; } - + private void checkBounds(int paramNumber) throws SQLException { if (paramNumber < 1) { - throw SQLError.createSQLException("Parameter index of '" + paramNumber + - "' is invalid.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + throw SQLError.createSQLException("Parameter index of '" + + paramNumber + "' is invalid.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } - + if (paramNumber > this.parameterCount) { - throw SQLError.createSQLException("Parameter index of '" + paramNumber + - "' is greater than number of parameters, which is '" + - this.parameterCount + "'.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - + throw SQLError.createSQLException("Parameter index of '" + + paramNumber + + "' is greater than number of parameters, which is '" + + this.parameterCount + "'.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public Object unwrap(Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return Util.cast(iface, this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlSavepoint.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlSavepoint.java (.../MysqlSavepoint.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/MysqlSavepoint.java (.../MysqlSavepoint.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.rmi.server.UID; @@ -42,7 +41,8 @@ int uidLength = uidStr.length(); - StringBuffer safeString = new StringBuffer(uidLength); + StringBuffer safeString = new StringBuffer(uidLength+1); + safeString.append('_'); for (int i = 0; i < uidLength; i++) { char c = uidStr.charAt(i); @@ -58,6 +58,8 @@ } private String savepointName; + + private ExceptionInterceptor exceptionInterceptor; /** * Creates an unnamed savepoint. @@ -67,8 +69,8 @@ * @throws SQLException * if an error occurs */ - MysqlSavepoint() throws SQLException { - this(getUniqueId()); + MysqlSavepoint(ExceptionInterceptor exceptionInterceptor) throws SQLException { + this(getUniqueId(), exceptionInterceptor); } /** @@ -80,21 +82,23 @@ * @throws SQLException * if name == null or is empty. */ - MysqlSavepoint(String name) throws SQLException { + MysqlSavepoint(String name, ExceptionInterceptor exceptionInterceptor) throws SQLException { if (name == null || name.length() == 0) { throw SQLError.createSQLException("Savepoint name can not be NULL or empty", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } this.savepointName = name; + + this.exceptionInterceptor = exceptionInterceptor; } /** * @see java.sql.Savepoint#getSavepointId() */ public int getSavepointId() throws SQLException { throw SQLError.createSQLException("Only named savepoints are supported.", - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, exceptionInterceptor); } /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NamedPipeSocketFactory.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NamedPipeSocketFactory.java (.../NamedPipeSocketFactory.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NamedPipeSocketFactory.java (.../NamedPipeSocketFactory.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,45 +1,43 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; - import java.net.Socket; import java.net.SocketException; - +import java.sql.SQLException; import java.util.Properties; /** * A socket factory for named pipes (on Windows) * * @author Mark Matthews */ -public class NamedPipeSocketFactory implements SocketFactory { +public class NamedPipeSocketFactory implements SocketFactory, SocketMetadata { /** * A socket that encapsulates named pipes on Windows */ @@ -171,7 +169,7 @@ } } - private static final String NAMED_PIPE_PROP_NAME = "namedPipePath"; //$NON-NLS-1$ + public static final String NAMED_PIPE_PROP_NAME = "namedPipePath"; //$NON-NLS-1$ private Socket namedPipeSocket; @@ -216,4 +214,9 @@ return this.namedPipeSocket; } + + public boolean isLocallyConnected(ConnectionImpl conn) throws SQLException { + // Until I learn otherwise (or learn how to detect it), I assume that we are + return true; + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NdbLoadBalanceExceptionChecker.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NdbLoadBalanceExceptionChecker.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NdbLoadBalanceExceptionChecker.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,41 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + +public class NdbLoadBalanceExceptionChecker extends + StandardLoadBalanceExceptionChecker { + + public boolean shouldExceptionTriggerFailover(SQLException ex) { + return super.shouldExceptionTriggerFailover(ex) || checkNdbException(ex); + } + + private boolean checkNdbException(SQLException ex){ + // Have to parse the message since most NDB errors are mapped to the same DEMC, sadly. + return (ex.getMessage().startsWith("Lock wait timeout exceeded") || + (ex.getMessage().startsWith("Got temporary error") + && ex.getMessage().endsWith("from NDB"))); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NetworkResources.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NetworkResources.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NetworkResources.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,90 @@ +/* + Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +class NetworkResources { + private final Socket mysqlConnection; + private final InputStream mysqlInput; + private final OutputStream mysqlOutput; + + protected NetworkResources(Socket mysqlConnection, InputStream mysqlInput, OutputStream mysqlOutput) { + this.mysqlConnection = mysqlConnection; + this.mysqlInput = mysqlInput; + this.mysqlOutput = mysqlOutput; + } + + /** + * Forcibly closes the underlying socket to MySQL. + */ + protected final void forceClose() { + try { + try { + if (this.mysqlInput != null) { + this.mysqlInput.close(); + } + } finally { + if (this.mysqlConnection != null && !this.mysqlConnection.isClosed() && !this.mysqlConnection.isInputShutdown()) { + try { + this.mysqlConnection.shutdownInput(); + } catch (UnsupportedOperationException ex) { + // ignore, some sockets do not support this method + } + } + } + } catch (IOException ioEx) { + // we can't do anything constructive about this + } + + try { + try { + if (this.mysqlOutput != null) { + this.mysqlOutput.close(); + } + } finally { + if (this.mysqlConnection != null && !this.mysqlConnection.isClosed() && !this.mysqlConnection.isOutputShutdown()) { + try { + this.mysqlConnection.shutdownOutput(); + } catch (UnsupportedOperationException ex) { + // ignore, some sockets do not support this method + } + } + } + } catch (IOException ioEx) { + // we can't do anything constructive about this + } + + try { + if (this.mysqlConnection != null) { + this.mysqlConnection.close(); + } + } catch (IOException ioEx) { + // we can't do anything constructive about this + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NoSubInterceptorWrapper.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NoSubInterceptorWrapper.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NoSubInterceptorWrapper.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,79 @@ +/* + Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +/** + * Wraps statement interceptors during driver startup so that they don't produce + * different result sets than we expect. + */ +public class NoSubInterceptorWrapper implements StatementInterceptorV2 { + + private final StatementInterceptorV2 underlyingInterceptor; + + public NoSubInterceptorWrapper(StatementInterceptorV2 underlyingInterceptor) { + if (underlyingInterceptor == null) { + throw new RuntimeException("Interceptor to be wrapped can not be NULL"); + } + + this.underlyingInterceptor = underlyingInterceptor; + } + + public void destroy() { + underlyingInterceptor.destroy(); + } + + public boolean executeTopLevelOnly() { + return underlyingInterceptor.executeTopLevelOnly(); + } + + public void init(Connection conn, Properties props) throws SQLException { + underlyingInterceptor.init(conn, props); + } + + public ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection, + int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, + SQLException statementException) throws SQLException { + underlyingInterceptor.postProcess(sql, interceptedStatement, originalResultSet, + connection, warningCount, noIndexUsed, noGoodIndexUsed, statementException); + + return null; // don't allow result set substitution + } + + public ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException { + underlyingInterceptor.preProcess(sql, interceptedStatement, connection); + + return null; // don't allow result set substitution + } + + public StatementInterceptorV2 getUnderlyingInterceptor() { + return underlyingInterceptor; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NonRegisteringDriver.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NonRegisteringDriver.java (.../NonRegisteringDriver.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NonRegisteringDriver.java (.../NonRegisteringDriver.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,43 +1,43 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; import java.net.URLDecoder; -import java.sql.Connection; import java.sql.DriverPropertyInfo; import java.sql.SQLException; - import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Properties; import java.util.StringTokenizer; - +import java.util.concurrent.ConcurrentHashMap; /** * The Java SQL framework allows for multiple database drivers. Each driver * should supply a class that implements the Driver interface @@ -68,14 +68,54 @@ * @see java.sql.Driver */ public class NonRegisteringDriver implements java.sql.Driver { + private static final String ALLOWED_QUOTES = "\"'"; + private static final String REPLICATION_URL_PREFIX = "jdbc:mysql:replication://"; private static final String URL_PREFIX = "jdbc:mysql://"; private static final String MXJ_URL_PREFIX = "jdbc:mysql:mxj://"; - private static final String LOADBALANCE_URL_PREFIX = "jdbc:mysql:loadbalance://"; + public static final String LOADBALANCE_URL_PREFIX = "jdbc:mysql:loadbalance://"; + protected static final ConcurrentHashMap connectionPhantomRefs = new ConcurrentHashMap(); + + protected static final ReferenceQueue refQueue = new ReferenceQueue(); + + public static final String OS = getOSName(); + public static final String PLATFORM = getPlatform(); + public static final String LICENSE = "@MYSQL_CJ_LICENSE_TYPE@"; + public static final String RUNTIME_VENDOR = System.getProperty("java.vendor"); + public static final String RUNTIME_VERSION = System.getProperty("java.version"); + public static final String VERSION = "@MYSQL_CJ_VERSION@"; + public static final String NAME = "@MYSQL_CJ_DISPLAY_PROD_NAME@"; + + /* + * Standardizes OS name information to align with other drivers/clients + * for MySQL connection attributes + * + * @return the transformed, standardized OS name + */ + public static String getOSName() { + return System.getProperty("os.name"); + } + + /* + * Standardizes platform information to align with other drivers/clients + * for MySQL connection attributes + * + * @return the transformed, standardized platform details + */ + public static String getPlatform() { + return System.getProperty("os.arch"); + } + + + static { + AbandonedConnectionCleanupThread referenceThread = new AbandonedConnectionCleanupThread(); + referenceThread.setDaemon(true); + referenceThread.start(); + } /** * Key used to retreive the database value from the properties instance * passed to the driver. @@ -94,6 +134,8 @@ */ public static final String HOST_PROPERTY_KEY = "HOST"; + public static final String NUM_HOSTS_PROPERTY_KEY = "NUM_HOSTS"; + /** * Key used to retreive the password value from the properties instance * passed to the driver. @@ -122,6 +164,10 @@ */ public static final String USER_PROPERTY_KEY = "user"; + public static final String PROTOCOL_PROPERTY_KEY = "PROTOCOL"; + + public static final String PATH_PROPERTY_KEY = "PATH"; + /** * Gets the drivers major version number * @@ -156,10 +202,19 @@ */ protected static String[] parseHostPortPair(String hostPortPair) throws SQLException { - int portIndex = hostPortPair.indexOf(":"); //$NON-NLS-1$ + String[] splitValues = new String[2]; + if (StringUtils.startsWithIgnoreCaseAndWs(hostPortPair, "address")) { + splitValues[HOST_NAME_INDEX] = hostPortPair.trim(); + splitValues[PORT_NUMBER_INDEX] = null; + + return splitValues; + } + + int portIndex = hostPortPair.indexOf(":"); //$NON-NLS-1$ + String hostname = null; if (portIndex != -1) { @@ -173,7 +228,7 @@ } else { throw SQLError.createSQLException(Messages .getString("NonRegisteringDriver.37"), //$NON-NLS-1$ - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); } } else { splitValues[HOST_NAME_INDEX] = hostPortPair; @@ -281,24 +336,38 @@ return null; } + if (!"1".equals(props.getProperty(NUM_HOSTS_PROPERTY_KEY))) { + return connectFailover(url, info); + } + try { - Connection newConn = new com.mysql.jdbc.Connection(host(props), - port(props), props, database(props), url); - + Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance( + host(props), port(props), props, database(props), url); + return newConn; } catch (SQLException sqlEx) { // Don't wrap SQLExceptions, throw // them un-changed. throw sqlEx; } catch (Exception ex) { - throw SQLError.createSQLException(Messages + SQLException sqlEx = SQLError.createSQLException(Messages .getString("NonRegisteringDriver.17") //$NON-NLS-1$ + ex.toString() + Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$ - SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null); + + sqlEx.initCause(ex); + + throw sqlEx; } } + protected static void trackConnection(Connection newConn) { + + ConnectionPhantomReference phantomRef = new ConnectionPhantomReference((ConnectionImpl) newConn, refQueue); + connectionPhantomRefs.put(phantomRef, phantomRef); + } + private java.sql.Connection connectLoadBalanced(String url, Properties info) throws SQLException { Properties parsedProps = parseURL(url, info); @@ -307,28 +376,63 @@ return null; } - String hostValues = parsedProps.getProperty(HOST_PROPERTY_KEY); + // People tend to drop this in, it doesn't make sense + parsedProps.remove("roundRobinLoadBalance"); + + int numHosts = Integer.parseInt(parsedProps.getProperty(NUM_HOSTS_PROPERTY_KEY)); - List hostList = null; + List hostList = new ArrayList(); - if (hostValues != null) { - hostList = StringUtils.split(hostValues, ",", true); + for (int i = 0; i < numHosts; i++) { + int index = i + 1; + + hostList.add(parsedProps.getProperty(HOST_PROPERTY_KEY + "." + index) + ":" + + parsedProps.getProperty(PORT_PROPERTY_KEY + "." + index)); } - if (hostList == null) { - hostList = new ArrayList(); - hostList.add("localhost:3306"); - } - LoadBalancingConnectionProxy proxyBal = new LoadBalancingConnectionProxy( hostList, parsedProps); return (java.sql.Connection) java.lang.reflect.Proxy.newProxyInstance(this .getClass().getClassLoader(), - new Class[] { java.sql.Connection.class }, proxyBal); + new Class[] { com.mysql.jdbc.LoadBalancedConnection.class }, proxyBal); } + + private java.sql.Connection connectFailover(String url, Properties info) + throws SQLException { + Properties parsedProps = parseURL(url, info); - private java.sql.Connection connectReplicationConnection(String url, Properties info) + if (parsedProps == null) { + return null; + } + + // People tend to drop this in, it doesn't make sense + parsedProps.remove("roundRobinLoadBalance"); + parsedProps.setProperty("autoReconnect", "false"); + + int numHosts = Integer.parseInt(parsedProps + .getProperty(NUM_HOSTS_PROPERTY_KEY)); + + List hostList = new ArrayList(); + + for (int i = 0; i < numHosts; i++) { + int index = i + 1; + + hostList.add(parsedProps.getProperty(HOST_PROPERTY_KEY + "." + + index) + + ":" + + parsedProps.getProperty(PORT_PROPERTY_KEY + "." + index)); + } + + FailoverConnectionProxy connProxy = new FailoverConnectionProxy( + hostList, parsedProps); + + return (java.sql.Connection) java.lang.reflect.Proxy.newProxyInstance( + this.getClass().getClassLoader(), + new Class[] { com.mysql.jdbc.Connection.class }, connProxy); + } + + protected java.sql.Connection connectReplicationConnection(String url, Properties info) throws SQLException { Properties parsedProps = parseURL(url, info); @@ -343,61 +447,71 @@ // debugging slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave", "true"); + + int numHosts = Integer.parseInt(parsedProps.getProperty(NUM_HOSTS_PROPERTY_KEY)); - String hostValues = parsedProps.getProperty(HOST_PROPERTY_KEY); - - if (hostValues != null) { - StringTokenizer st = new StringTokenizer(hostValues, ","); - - StringBuffer masterHost = new StringBuffer(); - StringBuffer slaveHosts = new StringBuffer(); - - if (st.hasMoreTokens()) { - String[] hostPortPair = parseHostPortPair(st.nextToken()); - - if (hostPortPair[HOST_NAME_INDEX] != null) { - masterHost.append(hostPortPair[HOST_NAME_INDEX]); + if (numHosts < 2) { + throw SQLError + .createSQLException( + "Must specify at least one slave host to connect to for master/slave replication load-balancing functionality", + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); + } + List slaveHostList = new ArrayList(); + List masterHostList = new ArrayList(); + + + String firstHost = masterProps.getProperty(HOST_PROPERTY_KEY + ".1") + ":" + + masterProps.getProperty(PORT_PROPERTY_KEY + ".1"); + + boolean usesExplicitServerType = NonRegisteringDriver.isHostPropertiesList(firstHost); + + for (int i = 0; i < numHosts; i++) { + int index = i + 1; + + masterProps.remove(HOST_PROPERTY_KEY + "." + index); + masterProps.remove(PORT_PROPERTY_KEY + "." + index); + slavesProps.remove(HOST_PROPERTY_KEY + "." + index); + slavesProps.remove(PORT_PROPERTY_KEY + "." + index); + + String host = parsedProps.getProperty(HOST_PROPERTY_KEY + "." + index); + String port = parsedProps.getProperty(PORT_PROPERTY_KEY + "." + index); + if(usesExplicitServerType) { + if(isHostMaster(host)) { + masterHostList.add(host); + } else { + slaveHostList.add(host); } - - if (hostPortPair[PORT_NUMBER_INDEX] != null) { - masterHost.append(":"); - masterHost.append(hostPortPair[PORT_NUMBER_INDEX]); - } - } - - boolean firstSlaveHost = true; - - while (st.hasMoreTokens()) { - String[] hostPortPair = parseHostPortPair(st.nextToken()); - - if (!firstSlaveHost) { - slaveHosts.append(","); + } else { + if(i == 0) { + masterHostList.add(host + ":" + port); } else { - firstSlaveHost = false; + slaveHostList.add(host + ":" + port); } - - if (hostPortPair[HOST_NAME_INDEX] != null) { - slaveHosts.append(hostPortPair[HOST_NAME_INDEX]); - } - - if (hostPortPair[PORT_NUMBER_INDEX] != null) { - slaveHosts.append(":"); - slaveHosts.append(hostPortPair[PORT_NUMBER_INDEX]); - } } + } - if (slaveHosts.length() == 0) { - throw SQLError - .createSQLException( - "Must specify at least one slave host to connect to for master/slave replication load-balancing functionality", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } + slavesProps.remove(NUM_HOSTS_PROPERTY_KEY); + masterProps.remove(NUM_HOSTS_PROPERTY_KEY); + masterProps.remove(HOST_PROPERTY_KEY); + masterProps.remove(PORT_PROPERTY_KEY); + slavesProps.remove(HOST_PROPERTY_KEY); + slavesProps.remove(PORT_PROPERTY_KEY); + - masterProps.setProperty(HOST_PROPERTY_KEY, masterHost.toString()); - slavesProps.setProperty(HOST_PROPERTY_KEY, slaveHosts.toString()); + return new ReplicationConnection(masterProps, slavesProps, masterHostList, slaveHostList); + } + + + + private boolean isHostMaster(String host) { + if (NonRegisteringDriver.isHostPropertiesList(host)) { + Properties hostSpecificProps = NonRegisteringDriver.expandHostKeyValues(host); + if(hostSpecificProps.containsKey("type") && + "master".equalsIgnoreCase(hostSpecificProps.get("type").toString())) { + return true; + } } - - return new ReplicationConnection(masterProps, slavesProps); + return false; } /** @@ -421,10 +535,6 @@ return getMajorVersionInternal(); } - // - // return the value of any property this driver knows about - // - /** * Get the drivers minor version number * @@ -497,7 +607,7 @@ passwordProp.description = Messages .getString("NonRegisteringDriver.16"); //$NON-NLS-1$ - DriverPropertyInfo[] dpi = ConnectionProperties + DriverPropertyInfo[] dpi = ConnectionPropertiesImpl .exposeAsDriverPropertyInfo(info, 5); dpi[0] = hostProp; @@ -509,6 +619,10 @@ return dpi; } + // + // return the value of any property this driver knows about + // + /** * Returns the hostname property * @@ -560,6 +674,7 @@ int beginningOfSlashes = url.indexOf("//"); if (StringUtils.startsWithIgnoreCase(url, MXJ_URL_PREFIX)) { + urlProps .setProperty("socketFactory", "com.mysql.management.driverlaunched.ServerLauncherSocketFactory"); @@ -614,7 +729,7 @@ String hostStuff = null; - int slashIndex = url.indexOf("/"); //$NON-NLS-1$ + int slashIndex = StringUtils.indexOfIgnoreCaseRespectMarker(0, url, "/", ALLOWED_QUOTES, ALLOWED_QUOTES, true); //$NON-NLS-1$ if (slashIndex != -1) { hostStuff = url.substring(0, slashIndex); @@ -627,10 +742,39 @@ hostStuff = url; } - if ((hostStuff != null) && (hostStuff.length() > 0)) { - urlProps.put(HOST_PROPERTY_KEY, hostStuff); //$NON-NLS-1$ + int numHosts = 0; + + if ((hostStuff != null) && (hostStuff.trim().length() > 0)) { + List hosts = StringUtils.split(hostStuff, ",", ALLOWED_QUOTES, ALLOWED_QUOTES, false); + + + for (String hostAndPort : hosts) { + numHosts++; + + String[] hostPortPair = parseHostPortPair(hostAndPort); + + if (hostPortPair[HOST_NAME_INDEX] != null && hostPortPair[HOST_NAME_INDEX].trim().length() > 0) { + urlProps.setProperty(HOST_PROPERTY_KEY + "." + numHosts, hostPortPair[HOST_NAME_INDEX]); + } else { + urlProps.setProperty(HOST_PROPERTY_KEY + "." + numHosts, "localhost"); + } + + if (hostPortPair[PORT_NUMBER_INDEX] != null) { + urlProps.setProperty(PORT_PROPERTY_KEY + "." + numHosts, hostPortPair[PORT_NUMBER_INDEX]); + } else { + urlProps.setProperty(PORT_PROPERTY_KEY + "." + numHosts, "3306"); + } + } + } else { + numHosts = 1; + urlProps.setProperty(HOST_PROPERTY_KEY + ".1", "localhost"); + urlProps.setProperty(PORT_PROPERTY_KEY + ".1", "3306"); } + urlProps.setProperty(NUM_HOSTS_PROPERTY_KEY, String.valueOf(numHosts)); + urlProps.setProperty(HOST_PROPERTY_KEY, urlProps.getProperty(HOST_PROPERTY_KEY + ".1")); + urlProps.setProperty(PORT_PROPERTY_KEY, urlProps.getProperty(PORT_PROPERTY_KEY + ".1")); + String propertiesTransformClassName = urlProps .getProperty(PROPERTIES_TRANSFORM_KEY); @@ -646,24 +790,24 @@ + propertiesTransformClassName + "' due to underlying exception: " + e.toString(), - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); } catch (IllegalAccessException e) { throw SQLError.createSQLException( "Unable to create properties transform instance '" + propertiesTransformClassName + "' due to underlying exception: " + e.toString(), - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); } catch (ClassNotFoundException e) { throw SQLError.createSQLException( "Unable to create properties transform instance '" + propertiesTransformClassName + "' due to underlying exception: " + e.toString(), - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); } } - + if (Util.isColdFusion() && urlProps.getProperty("autoConfigureForColdFusion", "true").equalsIgnoreCase("true")) { String configs = urlProps.getProperty(USE_CONFIG_PROPERTY_KEY); @@ -694,14 +838,14 @@ } if (configNames != null) { - List splitNames = StringUtils.split(configNames, ",", true); + List splitNames = StringUtils.split(configNames, ",", true); Properties configProps = new Properties(); - Iterator namesIter = splitNames.iterator(); + Iterator namesIter = splitNames.iterator(); while (namesIter.hasNext()) { - String configName = (String) namesIter.next(); + String configName = namesIter.next(); try { InputStream configAsStream = getClass() @@ -713,20 +857,23 @@ .createSQLException( "Can't find configuration template named '" + configName + "'", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); } configProps.load(configAsStream); } catch (IOException ioEx) { - throw SQLError.createSQLException( + SQLException sqlEx = SQLError.createSQLException( "Unable to load configuration template '" + configName + "' due to underlying IOException: " + ioEx, - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); + SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null); + sqlEx.initCause(ioEx); + + throw sqlEx; } } - Iterator propsIter = urlProps.keySet().iterator(); + Iterator propsIter = urlProps.keySet().iterator(); while (propsIter.hasNext()) { String key = propsIter.next().toString(); @@ -740,12 +887,14 @@ // Properties passed in should override ones in URL if (defaults != null) { - Iterator propsIter = defaults.keySet().iterator(); + Iterator propsIter = defaults.keySet().iterator(); while (propsIter.hasNext()) { String key = propsIter.next().toString(); - String property = defaults.getProperty(key); - urlProps.setProperty(key, property); + if (!key.equals(NUM_HOSTS_PROPERTY_KEY)) { + String property = defaults.getProperty(key); + urlProps.setProperty(key, property); + } } } @@ -777,4 +926,79 @@ public String property(String name, Properties props) { return props.getProperty(name); } + + + /** + * Expands hosts of the form address=(protocol=tcp)(host=localhost)(port=3306) + * into a java.util.Properties. Special characters (in this case () and =) must be quoted. + * Any values that are string-quoted ("" or '') are also stripped of quotes. + */ + public static Properties expandHostKeyValues(String host) { + Properties hostProps = new Properties(); + + if (isHostPropertiesList(host)) { + host = host.substring("address=".length() + 1); + List hostPropsList = StringUtils.split(host, ")", "'\"", "'\"", true); + + for (String propDef : hostPropsList) { + if (propDef.startsWith("(")) { + propDef = propDef.substring(1); + } + + List kvp = StringUtils.split(propDef, "=", "'\"", "'\"", true); + + String key = kvp.get(0); + String value = kvp.size() > 1 ? kvp.get(1) : null; + + if (value != null && ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'")))) { + value = value.substring(1, value.length() - 1); + } + + if (value != null) { + if (HOST_PROPERTY_KEY.equalsIgnoreCase(key) || + DBNAME_PROPERTY_KEY.equalsIgnoreCase(key) || + PORT_PROPERTY_KEY.equalsIgnoreCase(key) || + PROTOCOL_PROPERTY_KEY.equalsIgnoreCase(key) || + PATH_PROPERTY_KEY.equalsIgnoreCase(key)) { + key = key.toUpperCase(Locale.ENGLISH); + } else if (USER_PROPERTY_KEY.equalsIgnoreCase(key) || + PASSWORD_PROPERTY_KEY.equalsIgnoreCase(key)) { + key = key.toLowerCase(Locale.ENGLISH); + } + + hostProps.setProperty(key, value); + } + } + } + + return hostProps; + } + + public static boolean isHostPropertiesList(String host) { + return host != null && StringUtils.startsWithIgnoreCase(host, "address="); + } + + static class ConnectionPhantomReference extends PhantomReference { + private NetworkResources io; + + ConnectionPhantomReference(ConnectionImpl connectionImpl, ReferenceQueue q) { + super(connectionImpl, q); + + try { + io = connectionImpl.getIO().getNetworkResources(); + } catch (SQLException e) { + // if we somehow got here and there's really no i/o, we deal with it later + } + } + + void cleanup() { + if (io != null) { + try { + io.forceClose(); + } finally { + io = null; + } + } + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NonRegisteringReplicationDriver.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NonRegisteringReplicationDriver.java (.../NonRegisteringReplicationDriver.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NonRegisteringReplicationDriver.java (.../NonRegisteringReplicationDriver.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,24 +1,23 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ @@ -27,7 +26,6 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; -import java.util.StringTokenizer; /** * Driver that opens two connections, one two a replication master, and another @@ -48,71 +46,6 @@ * @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */ public Connection connect(String url, Properties info) throws SQLException { - Properties parsedProps = parseURL(url, info); - - if (parsedProps == null) { - return null; - } - - Properties masterProps = (Properties)parsedProps.clone(); - Properties slavesProps = (Properties)parsedProps.clone(); - - // Marker used for further testing later on, also when - // debugging - slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave", "true"); - - String hostValues = parsedProps.getProperty(HOST_PROPERTY_KEY); - - if (hostValues != null) { - StringTokenizer st = new StringTokenizer(hostValues, ","); - - StringBuffer masterHost = new StringBuffer(); - StringBuffer slaveHosts = new StringBuffer(); - - if (st.hasMoreTokens()) { - String[] hostPortPair = parseHostPortPair(st.nextToken()); - - if (hostPortPair[HOST_NAME_INDEX] != null) { - masterHost.append(hostPortPair[HOST_NAME_INDEX]); - } - - if (hostPortPair[PORT_NUMBER_INDEX] != null) { - masterHost.append(":"); - masterHost.append(hostPortPair[PORT_NUMBER_INDEX]); - } - } - - boolean firstSlaveHost = true; - - while (st.hasMoreTokens()) { - String[] hostPortPair = parseHostPortPair(st.nextToken()); - - if (!firstSlaveHost) { - slaveHosts.append(","); - } else { - firstSlaveHost = false; - } - - if (hostPortPair[HOST_NAME_INDEX] != null) { - slaveHosts.append(hostPortPair[HOST_NAME_INDEX]); - } - - if (hostPortPair[PORT_NUMBER_INDEX] != null) { - slaveHosts.append(":"); - slaveHosts.append(hostPortPair[PORT_NUMBER_INDEX]); - } - } - - if (slaveHosts.length() == 0) { - throw SQLError.createSQLException( - "Must specify at least one slave host to connect to for master/slave replication load-balancing functionality", - SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); - } - - masterProps.setProperty(HOST_PROPERTY_KEY, masterHost.toString()); - slavesProps.setProperty(HOST_PROPERTY_KEY, slaveHosts.toString()); - } - - return new ReplicationConnection(masterProps, slavesProps); + return connectReplicationConnection(url, info); } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NotImplemented.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NotImplemented.java (.../NotImplemented.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NotImplemented.java (.../NotImplemented.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** @@ -30,6 +29,9 @@ * @author Mark Matthews */ public class NotImplemented extends java.sql.SQLException { + + static final long serialVersionUID = 7768433826547599990L; + // ~ Constructors // ----------------------------------------------------------- Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/NotUpdatable.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/NotUpdatable.java (.../NotUpdatable.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/NotUpdatable.java (.../NotUpdatable.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/OperationNotSupportedException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/OperationNotSupportedException.java (.../OperationNotSupportedException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/OperationNotSupportedException.java (.../OperationNotSupportedException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,14 +1,34 @@ /* - * Created on Sep 23, 2004 - * - * TODO To change the template for this generated file go to - * Window - Preferences - Java - Code Style - Code Templates + Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ + package com.mysql.jdbc; import java.sql.SQLException; class OperationNotSupportedException extends SQLException { + + static final long serialVersionUID = 474918612056813430L; + OperationNotSupportedException() { super( Messages.getString("RowDataDynamic.10"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/OutputStreamWatcher.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/OutputStreamWatcher.java (.../OutputStreamWatcher.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/OutputStreamWatcher.java (.../OutputStreamWatcher.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/PacketTooBigException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/PacketTooBigException.java (.../PacketTooBigException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/PacketTooBigException.java (.../PacketTooBigException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; @@ -32,6 +31,9 @@ * @author Mark Matthews */ public class PacketTooBigException extends SQLException { + + static final long serialVersionUID = 7248633977685452174L; + // ~ Constructors // ----------------------------------------------------------- Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ParameterBindings.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ParameterBindings.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ParameterBindings.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,95 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Clob; +import java.sql.Date; +import java.sql.Ref; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; + +/** + * Interface to allow PreparedStatement implementations to expose + * their parameter bindings to StatementInterceptors. + * + * @version $Id$ + */ +public interface ParameterBindings { + + public abstract Array getArray(int parameterIndex) throws SQLException; + + public abstract InputStream getAsciiStream(int parameterIndex) throws SQLException; + + public abstract BigDecimal getBigDecimal(int parameterIndex) throws SQLException; + + public abstract InputStream getBinaryStream(int parameterIndex) throws SQLException; + + public abstract java.sql.Blob getBlob(int parameterIndex) throws SQLException; + + public abstract boolean getBoolean(int parameterIndex) throws SQLException; + + public abstract byte getByte(int parameterIndex) throws SQLException; + + public abstract byte[] getBytes(int parameterIndex) throws SQLException; + + public abstract Reader getCharacterStream(int parameterIndex) throws SQLException; + + public abstract Clob getClob(int parameterIndex) throws SQLException; + + public abstract Date getDate(int parameterIndex) throws SQLException; + + public abstract double getDouble(int parameterIndex) throws SQLException; + + public abstract float getFloat(int parameterIndex) throws SQLException; + + public abstract int getInt(int parameterIndex) throws SQLException; + + public abstract long getLong(int parameterIndex) throws SQLException; + + public abstract Reader getNCharacterStream(int parameterIndex) throws SQLException; + + public abstract Reader getNClob(int parameterIndex) throws SQLException; + + public abstract Object getObject(int parameterIndex) throws SQLException; + + public abstract Ref getRef(int parameterIndex) throws SQLException; + + public abstract short getShort(int parameterIndex) throws SQLException; + + public abstract String getString(int parameterIndex) throws SQLException; + + public abstract Time getTime(int parameterIndex) throws SQLException; + + public abstract Timestamp getTimestamp(int parameterIndex) throws SQLException; + + public abstract URL getURL(int parameterIndex) throws SQLException; + + public abstract boolean isNull(int parameterIndex) throws SQLException; +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/PerConnectionLRUFactory.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/PerConnectionLRUFactory.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/PerConnectionLRUFactory.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,96 @@ +/* + Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; +import java.util.Set; + +import com.mysql.jdbc.PreparedStatement.ParseInfo; +import com.mysql.jdbc.util.LRUCache; + +public class PerConnectionLRUFactory implements CacheAdapterFactory { + + public CacheAdapter getInstance(Connection forConnection, + String url, int cacheMaxSize, int maxKeySize, + Properties connectionProperties) throws SQLException { + + return new PerConnectionLRU(forConnection, cacheMaxSize, maxKeySize); + } + + class PerConnectionLRU implements CacheAdapter { + private final int cacheSqlLimit; + private final LRUCache cache; + private final Connection conn; + + protected PerConnectionLRU(Connection forConnection, int cacheMaxSize, + int maxKeySize) { + final int cacheSize = cacheMaxSize; + cacheSqlLimit = maxKeySize; + cache = new LRUCache(cacheSize); + conn = forConnection; + } + + public ParseInfo get(String key) { + if (key == null || key.length() > cacheSqlLimit) { + return null; + } + + synchronized (conn.getConnectionMutex()) { + return (ParseInfo) cache.get(key); + } + } + + public void put(String key, ParseInfo value) { + if (key == null || key.length() > cacheSqlLimit) { + return; + } + + synchronized (conn.getConnectionMutex()) { + cache.put(key, value); + } + } + + public void invalidate(String key) { + synchronized (conn.getConnectionMutex()) { + cache.remove(key); + } + } + + public void invalidateAll(Set keys) { + synchronized (conn.getConnectionMutex()) { + for (String key : keys) { + cache.remove(key); + } + } + + } + + public void invalidateAll() { + synchronized (conn.getConnectionMutex()) { + cache.clear(); + } + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/PerVmServerConfigCacheFactory.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/PerVmServerConfigCacheFactory.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/PerVmServerConfigCacheFactory.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,64 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class PerVmServerConfigCacheFactory implements CacheAdapterFactory> { + static final ConcurrentHashMap> serverConfigByUrl = new ConcurrentHashMap>(); + + private static final CacheAdapter> serverConfigCache = new CacheAdapter>() { + + public Map get(String key) { + return serverConfigByUrl.get(key); + } + + public void put(String key, Map value) { + serverConfigByUrl.putIfAbsent(key, value); + } + + public void invalidate(String key) { + serverConfigByUrl.remove(key); + } + + public void invalidateAll(Set keys) { + for (String key : keys) { + serverConfigByUrl.remove(key); + } + } + + public void invalidateAll() { + serverConfigByUrl.clear(); + }}; + + public CacheAdapter> getInstance( + Connection forConn, String url, int cacheMaxSize, int maxKeySize, + Properties connectionProperties) throws SQLException { + return serverConfigCache; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/PingTarget.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/PingTarget.java (.../PingTarget.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/PingTarget.java (.../PingTarget.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,25 +1,26 @@ /* - Copyright (C) 2007 MySQL AB + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ - + package com.mysql.jdbc; import java.sql.SQLException; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/PreparedStatement.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/PreparedStatement.java (.../PreparedStatement.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/PreparedStatement.java (.../PreparedStatement.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.ByteArrayInputStream; @@ -32,11 +31,18 @@ import java.io.Reader; import java.io.StringReader; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; import java.sql.Array; import java.sql.Clob; +import java.sql.DatabaseMetaData; +import java.sql.Date; import java.sql.ParameterMetaData; import java.sql.Ref; import java.sql.SQLException; @@ -47,13 +53,17 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Locale; import java.util.TimeZone; -import com.mysql.jdbc.Statement.CancelTask; +import com.mysql.jdbc.exceptions.MySQLStatementCancelledException; import com.mysql.jdbc.exceptions.MySQLTimeoutException; import com.mysql.jdbc.profiler.ProfilerEvent; + /** * A SQL Statement is pre-compiled and stored in a PreparedStatement object. * This object can then be used to efficiently execute this statement multiple @@ -78,18 +88,53 @@ * @see java.sql.ResultSet * @see java.sql.PreparedStatement */ -public class PreparedStatement extends com.mysql.jdbc.Statement implements +public class PreparedStatement extends com.mysql.jdbc.StatementImpl implements java.sql.PreparedStatement { - class BatchParams { - boolean[] isNull = null; + private static final Constructor JDBC_4_PSTMT_2_ARG_CTOR; + private static final Constructor JDBC_4_PSTMT_3_ARG_CTOR; + private static final Constructor JDBC_4_PSTMT_4_ARG_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_PSTMT_2_ARG_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4PreparedStatement") + .getConstructor( + new Class[] { MySQLConnection.class, String.class }); + JDBC_4_PSTMT_3_ARG_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4PreparedStatement") + .getConstructor( + new Class[] { MySQLConnection.class, String.class, + String.class }); + JDBC_4_PSTMT_4_ARG_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4PreparedStatement") + .getConstructor( + new Class[] { MySQLConnection.class, String.class, + String.class, ParseInfo.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_PSTMT_2_ARG_CTOR = null; + JDBC_4_PSTMT_3_ARG_CTOR = null; + JDBC_4_PSTMT_4_ARG_CTOR = null; + } + } + + public class BatchParams { + public boolean[] isNull = null; - boolean[] isStream = null; + public boolean[] isStream = null; - InputStream[] parameterStreams = null; + public InputStream[] parameterStreams = null; - byte[][] parameterStrings = null; + public byte[][] parameterStrings = null; - int[] streamLengths = null; + public int[] streamLengths = null; BatchParams(byte[][] strings, InputStream[] streams, boolean[] isStreamFlags, int[] lengths, boolean[] isNullFlags) { @@ -128,228 +173,518 @@ class ParseInfo { char firstStmtChar = 0; - boolean foundLimitClause = false; - boolean foundLoadData = false; long lastUsed = 0; int statementLength = 0; - + int statementStartPos = 0; + boolean canRewriteAsMultiValueInsert = false; + byte[][] staticSql = null; + boolean isOnDuplicateKeyUpdate = false; + + int locationOfOnDuplicateKeyUpdate = -1; + + String valuesClause; + + boolean parametersInDuplicateKeyClause = false; + /** * Represents the "parsed" state of a client-side * prepared statement, with the statement broken up into * it's static and dynamic (where parameters are bound) * parts. */ - public ParseInfo(String sql, Connection conn, + ParseInfo(String sql, MySQLConnection conn, java.sql.DatabaseMetaData dbmd, String encoding, SingleByteCharsetConverter converter) throws SQLException { - if (sql == null) { - throw SQLError.createSQLException(Messages - .getString("PreparedStatement.61"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } + this(sql, conn, dbmd, encoding, converter, true); + } + + public ParseInfo(String sql, MySQLConnection conn, + java.sql.DatabaseMetaData dbmd, String encoding, + SingleByteCharsetConverter converter, boolean buildRewriteInfo) throws SQLException { + try { + if (sql == null) { + throw SQLError.createSQLException(Messages + .getString("PreparedStatement.61"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } - this.lastUsed = System.currentTimeMillis(); + this.locationOfOnDuplicateKeyUpdate = getOnDuplicateKeyLocation(sql); + this.isOnDuplicateKeyUpdate = this.locationOfOnDuplicateKeyUpdate != -1; + + this.lastUsed = System.currentTimeMillis(); - String quotedIdentifierString = dbmd.getIdentifierQuoteString(); + String quotedIdentifierString = dbmd.getIdentifierQuoteString(); - char quotedIdentifierChar = 0; + char quotedIdentifierChar = 0; - if ((quotedIdentifierString != null) - && !quotedIdentifierString.equals(" ") //$NON-NLS-1$ - && (quotedIdentifierString.length() > 0)) { - quotedIdentifierChar = quotedIdentifierString.charAt(0); - } + if ((quotedIdentifierString != null) + && !quotedIdentifierString.equals(" ") //$NON-NLS-1$ + && (quotedIdentifierString.length() > 0)) { + quotedIdentifierChar = quotedIdentifierString.charAt(0); + } - this.statementLength = sql.length(); + this.statementLength = sql.length(); - ArrayList endpointList = new ArrayList(); - boolean inQuotes = false; - char quoteChar = 0; - boolean inQuotedId = false; - int lastParmEnd = 0; - int i; + ArrayList endpointList = new ArrayList(); + boolean inQuotes = false; + char quoteChar = 0; + boolean inQuotedId = false; + int lastParmEnd = 0; + int i; - int stopLookingForLimitClause = this.statementLength - 5; + boolean noBackslashEscapes = connection.isNoBackslashEscapesSet(); - this.foundLimitClause = false; - - boolean noBackslashEscapes = connection.isNoBackslashEscapesSet(); - - // we're not trying to be real pedantic here, but we'd like to - // skip comments at the beginning of statements, as frameworks - // such as Hibernate use them to aid in debugging - - statementStartPos = findStartOfStatement(sql); - - for (i = statementStartPos; i < this.statementLength; ++i) { - char c = sql.charAt(i); + // we're not trying to be real pedantic here, but we'd like to + // skip comments at the beginning of statements, as frameworks + // such as Hibernate use them to aid in debugging - if ((this.firstStmtChar == 0) && !Character.isWhitespace(c)) { - // Determine what kind of statement we're doing (_S_elect, - // _I_nsert, etc.) - this.firstStmtChar = Character.toUpperCase(c); - } + statementStartPos = findStartOfStatement(sql); - if (!noBackslashEscapes && - c == '\\' && i < (this.statementLength - 1)) { - i++; - continue; // next character is escaped - } - - // are we in a quoted identifier? - // (only valid when the id is not inside a 'string') - if (!inQuotes && (quotedIdentifierChar != 0) - && (c == quotedIdentifierChar)) { - inQuotedId = !inQuotedId; - } else if (!inQuotedId) { - // only respect quotes when not in a quoted identifier - - if (inQuotes) { - if (((c == '\'') || (c == '"')) && c == quoteChar) { - if (i < (this.statementLength - 1) && sql.charAt(i + 1) == quoteChar) { - i++; - continue; // inline quote escape + for (i = statementStartPos; i < this.statementLength; ++i) { + char c = sql.charAt(i); + + if ((this.firstStmtChar == 0) && Character.isLetter(c)) { + // Determine what kind of statement we're doing (_S_elect, + // _I_nsert, etc.) + this.firstStmtChar = Character.toUpperCase(c); + } + + if (!noBackslashEscapes && + c == '\\' && i < (this.statementLength - 1)) { + i++; + continue; // next character is escaped + } + + // are we in a quoted identifier? + // (only valid when the id is not inside a 'string') + if (!inQuotes && (quotedIdentifierChar != 0) + && (c == quotedIdentifierChar)) { + inQuotedId = !inQuotedId; + } else if (!inQuotedId) { + // only respect quotes when not in a quoted identifier + + if (inQuotes) { + if (((c == '\'') || (c == '"')) && c == quoteChar) { + if (i < (this.statementLength - 1) && sql.charAt(i + 1) == quoteChar) { + i++; + continue; // inline quote escape + } + + inQuotes = !inQuotes; + quoteChar = 0; + } else if (((c == '\'') || (c == '"')) && c == quoteChar) { + inQuotes = !inQuotes; + quoteChar = 0; } - - inQuotes = !inQuotes; - quoteChar = 0; - } else if (((c == '\'') || (c == '"')) && c == quoteChar) { - inQuotes = !inQuotes; - quoteChar = 0; - } - } else { - if (c == '#' + } else { + if (c == '#' || (c == '-' && (i + 1) < this.statementLength && sql .charAt(i + 1) == '-')) { - // run out to end of statement, or newline, - // whichever comes first - int endOfStmt = this.statementLength - 1; + // run out to end of statement, or newline, + // whichever comes first + int endOfStmt = this.statementLength - 1; - for (; i < endOfStmt; i++) { - c = sql.charAt(i); + for (; i < endOfStmt; i++) { + c = sql.charAt(i); - if (c == '\r' || c == '\n') { - break; + if (c == '\r' || c == '\n') { + break; + } } - } - continue; - } else if (c == '/' && (i + 1) < this.statementLength) { - // Comment? - char cNext = sql.charAt(i + 1); - - if (cNext == '*') { - i+= 2; - - for (int j = i; j < this.statementLength; j++) { - i++; - cNext = sql.charAt(j); - - if (cNext == '*' && (j + 1) < this.statementLength) { - if (sql.charAt(j + 1) == '/') { - i++; - - if (i < this.statementLength) { - c = sql.charAt(i); + continue; + } else if (c == '/' && (i + 1) < this.statementLength) { + // Comment? + char cNext = sql.charAt(i + 1); + + if (cNext == '*') { + i+= 2; + + for (int j = i; j < this.statementLength; j++) { + i++; + cNext = sql.charAt(j); + + if (cNext == '*' && (j + 1) < this.statementLength) { + if (sql.charAt(j + 1) == '/') { + i++; + + if (i < this.statementLength) { + c = sql.charAt(i); + } + + break; // comment done } - - break; // comment done } } } + } else if ((c == '\'') || (c == '"')) { + inQuotes = true; + quoteChar = c; } - } else if ((c == '\'') || (c == '"')) { - inQuotes = true; - quoteChar = c; } } + + if ((c == '?') && !inQuotes && !inQuotedId) { + endpointList.add(new int[] { lastParmEnd, i }); + lastParmEnd = i + 1; + + if (isOnDuplicateKeyUpdate && i > locationOfOnDuplicateKeyUpdate) { + parametersInDuplicateKeyClause = true; + } + } } - if ((c == '?') && !inQuotes && !inQuotedId) { - endpointList.add(new int[] { lastParmEnd, i }); - lastParmEnd = i + 1; + if (this.firstStmtChar == 'L') { + if (StringUtils.startsWithIgnoreCaseAndWs(sql, "LOAD DATA")) { //$NON-NLS-1$ + this.foundLoadData = true; + } else { + this.foundLoadData = false; + } + } else { + this.foundLoadData = false; } - if (!inQuotes && (i < stopLookingForLimitClause)) { - if ((c == 'L') || (c == 'l')) { - char posI1 = sql.charAt(i + 1); + endpointList.add(new int[] { lastParmEnd, this.statementLength }); + this.staticSql = new byte[endpointList.size()][]; - if ((posI1 == 'I') || (posI1 == 'i')) { - char posM = sql.charAt(i + 2); + for (i = 0; i < this.staticSql.length; i++) { + int[] ep = endpointList.get(i); + int end = ep[1]; + int begin = ep[0]; + int len = end - begin; - if ((posM == 'M') || (posM == 'm')) { - char posI2 = sql.charAt(i + 3); + if (this.foundLoadData) { + this.staticSql[i] = StringUtils.getBytes(sql, begin, len); + } else if (encoding == null) { + byte[] buf = new byte[len]; - if ((posI2 == 'I') || (posI2 == 'i')) { - char posT = sql.charAt(i + 4); + for (int j = 0; j < len; j++) { + buf[j] = (byte) sql.charAt(begin + j); + } - if ((posT == 'T') || (posT == 't')) { - foundLimitClause = true; - } - } - } + this.staticSql[i] = buf; + } else { + if (converter != null) { + this.staticSql[i] = StringUtils.getBytes(sql, + converter, encoding, connection + .getServerCharacterEncoding(), begin, + len, connection.parserKnowsUnicode(), getExceptionInterceptor()); + } else { + this.staticSql[i] = StringUtils.getBytes(sql, encoding, + connection.getServerCharacterEncoding(), begin, len, + connection.parserKnowsUnicode(), conn, getExceptionInterceptor()); } } } + } catch (StringIndexOutOfBoundsException oobEx) { + SQLException sqlEx = new SQLException("Parse error for " + sql); + sqlEx.initCause(oobEx); + + throw sqlEx; } + + + if (buildRewriteInfo) { + this.canRewriteAsMultiValueInsert = PreparedStatement + .canRewrite(sql, this.isOnDuplicateKeyUpdate, + this.locationOfOnDuplicateKeyUpdate, + this.statementStartPos) && !this.parametersInDuplicateKeyClause; - if (this.firstStmtChar == 'L') { - if (StringUtils.startsWithIgnoreCaseAndWs(sql, "LOAD DATA")) { //$NON-NLS-1$ - this.foundLoadData = true; - } else { - this.foundLoadData = false; + if (this.canRewriteAsMultiValueInsert + && conn.getRewriteBatchedStatements()) { + buildRewriteBatchedParams(sql, conn, dbmd, encoding, + converter); } + } + } + + private ParseInfo batchHead; + + private ParseInfo batchValues; + + private ParseInfo batchODKUClause; + + private void buildRewriteBatchedParams(String sql, MySQLConnection conn, + DatabaseMetaData metadata, String encoding, + SingleByteCharsetConverter converter) throws SQLException { + this.valuesClause = extractValuesClause(sql); + String odkuClause = isOnDuplicateKeyUpdate ? sql + .substring(locationOfOnDuplicateKeyUpdate) : null; + + String headSql = null; + + if (isOnDuplicateKeyUpdate) { + headSql = sql.substring(0, locationOfOnDuplicateKeyUpdate); } else { - this.foundLoadData = false; + headSql = sql; } - endpointList.add(new int[] { lastParmEnd, this.statementLength }); - this.staticSql = new byte[endpointList.size()][]; - char[] asCharArray = sql.toCharArray(); + this.batchHead = new ParseInfo(headSql, conn, metadata, encoding, + converter, false); + this.batchValues = new ParseInfo("," + this.valuesClause, conn, + metadata, encoding, converter, false); + this.batchODKUClause = null; - for (i = 0; i < this.staticSql.length; i++) { - int[] ep = (int[]) endpointList.get(i); - int end = ep[1]; - int begin = ep[0]; - int len = end - begin; + if (odkuClause != null && odkuClause.length() > 0) { + this.batchODKUClause = new ParseInfo("," + this.valuesClause + + " " + odkuClause, conn, metadata, encoding, + converter, false); + } + } - if (this.foundLoadData) { - String temp = new String(asCharArray, begin, len); - this.staticSql[i] = temp.getBytes(); - } else if (encoding == null) { - byte[] buf = new byte[len]; + private String extractValuesClause(String sql) throws SQLException { + String quoteCharStr = connection.getMetaData() + .getIdentifierQuoteString(); - for (int j = 0; j < len; j++) { - buf[j] = (byte) sql.charAt(begin + j); - } + int indexOfValues = -1; + int valuesSearchStart = statementStartPos; - this.staticSql[i] = buf; + while (indexOfValues == -1) { + if (quoteCharStr.length() > 0) { + indexOfValues = StringUtils.indexOfIgnoreCaseRespectQuotes( + valuesSearchStart, + originalSql, "VALUES", quoteCharStr.charAt(0), false); } else { - if (converter != null) { - this.staticSql[i] = StringUtils.getBytes(sql, - converter, encoding, connection - .getServerCharacterEncoding(), begin, - len, connection.parserKnowsUnicode()); + indexOfValues = StringUtils.indexOfIgnoreCase(valuesSearchStart, + originalSql, + "VALUES"); + } + + if (indexOfValues > 0) { + /* check if the char immediately preceding VALUES may be part of the table name */ + char c = originalSql.charAt(indexOfValues - 1); + if(!(Character.isWhitespace(c) || c == ')' || c == '`')){ + valuesSearchStart = indexOfValues + 6; + indexOfValues = -1; } else { - String temp = new String(asCharArray, begin, len); + /* check if the char immediately following VALUES may be whitespace or open parenthesis */ + c = originalSql.charAt(indexOfValues + 6); + if(!(Character.isWhitespace(c) || c == '(')){ + valuesSearchStart = indexOfValues + 6; + indexOfValues = -1; + } + } + } else { + break; + } + } - this.staticSql[i] = StringUtils.getBytes(temp, - encoding, connection - .getServerCharacterEncoding(), - connection.parserKnowsUnicode(), conn); + if (indexOfValues == -1) { + return null; + } + + int indexOfFirstParen = sql.indexOf('(', indexOfValues + 6); + + if (indexOfFirstParen == -1) { + return null; + } + + int endOfValuesClause = sql.lastIndexOf(')'); + + if (endOfValuesClause == -1) { + return null; + } + + if (isOnDuplicateKeyUpdate) { + endOfValuesClause = this.locationOfOnDuplicateKeyUpdate - 1; + } + + return sql.substring(indexOfFirstParen, endOfValuesClause + 1); + } + + /** + * Returns a ParseInfo for a multi-value INSERT for a batch of size numBatch (without parsing!). + */ + synchronized ParseInfo getParseInfoForBatch(int numBatch) { + AppendingBatchVisitor apv = new AppendingBatchVisitor(); + buildInfoForBatch(numBatch, apv); + + ParseInfo batchParseInfo = new ParseInfo(apv.getStaticSqlStrings(), + this.firstStmtChar, this.foundLoadData, this.isOnDuplicateKeyUpdate, + this.locationOfOnDuplicateKeyUpdate, this.statementLength, + this.statementStartPos); + + return batchParseInfo; + } + + /** + * Returns a preparable SQL string for the number of batched parameters, used by server-side prepared statements + * when re-writing batch INSERTs. + */ + + String getSqlForBatch(int numBatch) throws UnsupportedEncodingException { + ParseInfo batchInfo = getParseInfoForBatch(numBatch); + + return getSqlForBatch(batchInfo); + } + + /** + * Used for filling in the SQL for getPreparedSql() - for debugging + */ + String getSqlForBatch(ParseInfo batchInfo) throws UnsupportedEncodingException { + int size = 0; + final byte[][] sqlStrings = batchInfo.staticSql; + final int sqlStringsLength = sqlStrings.length; + + for (int i = 0; i < sqlStringsLength; i++) { + size += sqlStrings[i].length; + size++; // for the '?' + } + + StringBuffer buf = new StringBuffer(size); + + for (int i = 0; i < sqlStringsLength - 1; i++) { + buf.append(StringUtils.toString(sqlStrings[i], charEncoding)); + buf.append("?"); + } + + buf.append(StringUtils.toString(sqlStrings[sqlStringsLength - 1])); + + return buf.toString(); + } + + /** + * Builds a ParseInfo for the given batch size, without parsing. We use + * a visitor pattern here, because the if {}s make computing a size for the + * resultant byte[][] make this too complex, and we don't necessarily want to + * use a List for this, because the size can be dynamic, and thus we'll not be + * able to guess a good initial size for an array-based list, and it's not + * efficient to convert a LinkedList to an array. + */ + private void buildInfoForBatch(int numBatch, BatchVisitor visitor) { + final byte[][] headStaticSql = this.batchHead.staticSql; + final int headStaticSqlLength = headStaticSql.length; + + if (headStaticSqlLength > 1) { + for (int i = 0; i < headStaticSqlLength - 1; i++) { + visitor.append(headStaticSql[i]).increment(); + } + } + + // merge end of head, with beginning of a value clause + byte[] endOfHead = headStaticSql[headStaticSqlLength - 1]; + final byte[][] valuesStaticSql = this.batchValues.staticSql; + byte[] beginOfValues = valuesStaticSql[0]; + + visitor.merge(endOfHead, beginOfValues).increment(); + + int numValueRepeats = numBatch - 1; // first one is in the "head" + + if (this.batchODKUClause != null) { + numValueRepeats--; // Last one is in the ODKU clause + } + + final int valuesStaticSqlLength = valuesStaticSql.length; + byte[] endOfValues = valuesStaticSql[valuesStaticSqlLength - 1]; + + for (int i = 0; i < numValueRepeats; i++) { + for (int j = 1; j < valuesStaticSqlLength - 1; j++) { + visitor.append(valuesStaticSql[j]).increment(); + } + visitor.merge(endOfValues, beginOfValues).increment(); + } + + if (this.batchODKUClause != null) { + final byte[][] batchOdkuStaticSql = this.batchODKUClause.staticSql; + byte[] beginOfOdku = batchOdkuStaticSql[0]; + visitor.decrement().merge(endOfValues, beginOfOdku).increment(); + + final int batchOdkuStaticSqlLength = batchOdkuStaticSql.length; + + if (numBatch > 1) { + for (int i = 1; i < batchOdkuStaticSqlLength; i++) { + visitor.append(batchOdkuStaticSql[i]) + .increment(); } + } else { + visitor.decrement().append(batchOdkuStaticSql[(batchOdkuStaticSqlLength - 1)]); } + } else { + // Everything after the values clause, but not ODKU, which today is nothing + // but a syntax error, but we should still not mangle the SQL! + visitor.decrement().append(this.staticSql[this.staticSql.length - 1]); } } + + private ParseInfo(byte[][] staticSql, char firstStmtChar, + boolean foundLoadData, boolean isOnDuplicateKeyUpdate, + int locationOfOnDuplicateKeyUpdate, int statementLength, + int statementStartPos) { + this.firstStmtChar = firstStmtChar; + this.foundLoadData = foundLoadData; + this.isOnDuplicateKeyUpdate = isOnDuplicateKeyUpdate; + this.locationOfOnDuplicateKeyUpdate = locationOfOnDuplicateKeyUpdate; + this.statementLength = statementLength; + this.statementStartPos = statementStartPos; + this.staticSql = staticSql; + } } + interface BatchVisitor { + abstract BatchVisitor increment(); + + abstract BatchVisitor decrement(); + + abstract BatchVisitor append(byte[] values); + + abstract BatchVisitor merge(byte[] begin, byte[] end); + } + + class AppendingBatchVisitor implements BatchVisitor { + LinkedList statementComponents = new LinkedList(); + + public BatchVisitor append(byte[] values) { + statementComponents.addLast(values); + + return this; + } + + public BatchVisitor increment() { + // no-op + return this; + } + + public BatchVisitor decrement() { + statementComponents.removeLast(); + + return this; + } + + public BatchVisitor merge(byte[] front, byte[] back) { + int mergedLength = front.length + back.length; + byte[] merged = new byte[mergedLength]; + System.arraycopy(front, 0, merged, 0, front.length); + System.arraycopy(back, 0, merged, front.length, back.length); + statementComponents.addLast(merged); + return this; + } + + public byte[][] getStaticSqlStrings() { + byte[][] asBytes = new byte[this.statementComponents.size()][]; + this.statementComponents.toArray(asBytes); + + return asBytes; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + Iterator iter = this.statementComponents.iterator(); + while (iter.hasNext()) { + buf.append(StringUtils.toString(iter.next())); + } + + return buf.toString(); + } + + } + private final static byte[] HEX_DIGITS = new byte[] { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'A', @@ -371,7 +706,7 @@ * @throws IOException * DOCUMENT ME! */ - private static int readFully(Reader reader, char[] buf, int length) + protected static int readFully(Reader reader, char[] buf, int length) throws IOException { int numCharsRead = 0; @@ -404,13 +739,10 @@ */ protected char firstCharOfStmt = 0; - /** Does the SQL for this statement contain a 'limit' clause? */ - protected boolean hasLimitClause = false; - /** Is this query a LOAD DATA query? */ protected boolean isLoadDataQuery = false; - private boolean[] isNull = null; + protected boolean[] isNull = null; private boolean[] isStream = null; @@ -428,13 +760,19 @@ private byte[][] parameterValues = null; - private ParseInfo parseInfo; + /** + * Only used by statement interceptors at the moment to + * provide introspection of bound values + */ + protected int[] parameterTypes = null; + + protected ParseInfo parseInfo; private java.sql.ResultSetMetaData pstmtResultMetaData; private byte[][] staticSqlStrings = null; - private byte[] streamConvertBuf = new byte[4096]; + private byte[] streamConvertBuf = null; private int[] streamLengths = null; @@ -445,26 +783,75 @@ */ protected boolean useTrueBoolean = false; - private boolean usingAnsiMode; + protected boolean usingAnsiMode; - private String batchedValuesClause; + protected String batchedValuesClause; - /** Where does the statement text actually start? */ + private boolean doPingInstead; + private SimpleDateFormat ddf; + private SimpleDateFormat tdf; - private int statementAfterCommentsPos; + private boolean compensateForOnDuplicateKeyUpdate = false; + + /** Charset encoder used to escape if needed, such as Yen sign in SJIS */ + private CharsetEncoder charsetEncoder; + + /** Command index of currently executing batch command. */ + protected int batchCommandIndex = -1; + + protected boolean serverSupportsFracSecs; + + /** + * Creates a prepared statement instance -- We need to provide factory-style + * methods so we can support both JDBC3 (and older) and JDBC4 runtimes, + * otherwise the class verifier complains when it tries to load JDBC4-only + * interface classes that are present in JDBC4 method signatures. + */ + protected static PreparedStatement getInstance(MySQLConnection conn, + String catalog) throws SQLException { + if (!Util.isJdbc4()) { + return new PreparedStatement(conn, catalog); + } + + return (PreparedStatement) Util.handleNewInstance( + JDBC_4_PSTMT_2_ARG_CTOR, new Object[] { conn, catalog }, conn.getExceptionInterceptor()); + } + /** - * have we checked whether we can rewrite this statement as a multi-value - * insert? + * Creates a prepared statement instance -- We need to provide factory-style + * methods so we can support both JDBC3 (and older) and JDBC4 runtimes, + * otherwise the class verifier complains when it tries to load JDBC4-only + * interface classes that are present in JDBC4 method signatures. */ - private boolean hasCheckedForRewrite = false; + protected static PreparedStatement getInstance(MySQLConnection conn, String sql, + String catalog) throws SQLException { + if (!Util.isJdbc4()) { + return new PreparedStatement(conn, sql, catalog); + } - /** Can we actually rewrite this statement as a multi-value insert? */ + return (PreparedStatement) Util.handleNewInstance( + JDBC_4_PSTMT_3_ARG_CTOR, new Object[] { conn, sql, catalog }, conn.getExceptionInterceptor()); + } - private boolean canRewrite = false; + /** + * Creates a prepared statement instance -- We need to provide factory-style + * methods so we can support both JDBC3 (and older) and JDBC4 runtimes, + * otherwise the class verifier complains when it tries to load JDBC4-only + * interface classes that are present in JDBC4 method signatures. + */ - private boolean doPingInstead; + protected static PreparedStatement getInstance(MySQLConnection conn, String sql, + String catalog, ParseInfo cachedParseInfo) throws SQLException { + if (!Util.isJdbc4()) { + return new PreparedStatement(conn, sql, catalog, cachedParseInfo); + } + + return (PreparedStatement) Util.handleNewInstance( + JDBC_4_PSTMT_4_ARG_CTOR, new Object[] { conn, sql, catalog, + cachedParseInfo }, conn.getExceptionInterceptor()); + } /** * Constructor used by server-side prepared statements @@ -477,11 +864,19 @@ * @throws SQLException * if an error occurs */ - protected PreparedStatement(Connection conn, String catalog) + public PreparedStatement(MySQLConnection conn, String catalog) throws SQLException { super(conn, catalog); + + detectFractionalSecondsSupport(); + this.compensateForOnDuplicateKeyUpdate = this.connection.getCompensateOnDuplicateKeyUpdateCounts(); } + protected void detectFractionalSecondsSupport() throws SQLException { + this.serverSupportsFracSecs = this.connection != null && + this.connection.versionMeetsMinimum(5, 6, 4); + } + /** * Constructor for the PreparedStatement class. * @@ -495,15 +890,16 @@ * @throws SQLException * if a database error occurs. */ - public PreparedStatement(Connection conn, String sql, String catalog) + public PreparedStatement(MySQLConnection conn, String sql, String catalog) throws SQLException { super(conn, catalog); if (sql == null) { throw SQLError.createSQLException(Messages.getString("PreparedStatement.0"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } + detectFractionalSecondsSupport(); this.originalSql = sql; if (this.originalSql.startsWith(PING_MARKER)) { @@ -520,6 +916,11 @@ this.charEncoding, this.charConverter); initializeFromParseInfo(); + + this.compensateForOnDuplicateKeyUpdate = this.connection.getCompensateOnDuplicateKeyUpdateCounts(); + + if (conn.getRequiresEscapingEncoder()) + charsetEncoder = Charset.forName(conn.getEncoding()).newEncoder(); } /** @@ -537,15 +938,16 @@ * @throws SQLException * DOCUMENT ME! */ - public PreparedStatement(Connection conn, String sql, String catalog, + public PreparedStatement(MySQLConnection conn, String sql, String catalog, ParseInfo cachedParseInfo) throws SQLException { super(conn, catalog); if (sql == null) { throw SQLError.createSQLException(Messages.getString("PreparedStatement.1"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } + detectFractionalSecondsSupport(); this.originalSql = sql; this.dbmd = this.connection.getMetaData(); @@ -557,6 +959,11 @@ this.usingAnsiMode = !this.connection.useAnsiQuotedIdentifiers(); initializeFromParseInfo(); + + this.compensateForOnDuplicateKeyUpdate = this.connection.getCompensateOnDuplicateKeyUpdateCounts(); + + if (conn.getRequiresEscapingEncoder()) + charsetEncoder = Charset.forName(conn.getEncoding()).newEncoder(); } /** @@ -565,103 +972,131 @@ * @exception SQLException * if a database-access error occurs. * - * @see Statement#addBatch + * @see StatementImpl#addBatch */ public void addBatch() throws SQLException { - if (this.batchedArgs == null) { - this.batchedArgs = new ArrayList(); + synchronized (checkClosed().getConnectionMutex()) { + if (this.batchedArgs == null) { + this.batchedArgs = new ArrayList(); + } + + for (int i = 0; i < this.parameterValues.length; i++) { + checkAllParametersSet(this.parameterValues[i], + this.parameterStreams[i], i); + } + + this.batchedArgs.add(new BatchParams(this.parameterValues, + this.parameterStreams, this.isStream, this.streamLengths, + this.isNull)); } - - this.batchedArgs.add(new BatchParams(this.parameterValues, - this.parameterStreams, this.isStream, this.streamLengths, - this.isNull)); } - public synchronized void addBatch(String sql) throws SQLException { - this.batchHasPlainStatements = true; - - super.addBatch(sql); + public void addBatch(String sql) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.batchHasPlainStatements = true; + + super.addBatch(sql); + } } - protected String asSql() throws SQLException { + public String asSql() throws SQLException { return asSql(false); } - protected String asSql(boolean quoteStreamsAndUnknowns) throws SQLException { - if (this.isClosed) { - return "statement has been closed, no further internal information available"; - } - - StringBuffer buf = new StringBuffer(); - - try { - for (int i = 0; i < this.parameterCount; ++i) { - if (this.charEncoding != null) { - buf.append(new String(this.staticSqlStrings[i], - this.charEncoding)); - } else { - buf.append(new String(this.staticSqlStrings[i])); - } - - if ((this.parameterValues[i] == null) && !this.isStream[i]) { - if (quoteStreamsAndUnknowns) { - buf.append("'"); + public String asSql(boolean quoteStreamsAndUnknowns) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + StringBuffer buf = new StringBuffer(); + + try { + int realParameterCount = this.parameterCount + getParameterIndexOffset(); + Object batchArg = null; + if (batchCommandIndex != -1) + batchArg = batchedArgs.get(batchCommandIndex); + + for (int i = 0; i < realParameterCount; ++i) { + if (this.charEncoding != null) { + buf.append(StringUtils.toString(this.staticSqlStrings[i], + this.charEncoding)); + } else { + buf.append(StringUtils.toString(this.staticSqlStrings[i])); } - - buf.append("** NOT SPECIFIED **"); //$NON-NLS-1$ - - if (quoteStreamsAndUnknowns) { - buf.append("'"); + + byte val[] = null; + if (batchArg != null && batchArg instanceof String) { + buf.append((String)batchArg); + continue; } - } else if (this.isStream[i]) { - if (quoteStreamsAndUnknowns) { - buf.append("'"); - } - - buf.append("** STREAM DATA **"); //$NON-NLS-1$ - - if (quoteStreamsAndUnknowns) { - buf.append("'"); - } - } else { - if (this.charConverter != null) { - buf.append(this.charConverter - .toString(this.parameterValues[i])); + if (batchCommandIndex == -1) + val = parameterValues[i]; + else + val = ((BatchParams)batchArg).parameterStrings[i]; + + boolean isStreamParam = false; + if (batchCommandIndex == -1) + isStreamParam = isStream[i]; + else + isStreamParam = ((BatchParams)batchArg).isStream[i]; + + if ((val == null) && !isStreamParam) { + if (quoteStreamsAndUnknowns) { + buf.append("'"); + } + + buf.append("** NOT SPECIFIED **"); //$NON-NLS-1$ + + if (quoteStreamsAndUnknowns) { + buf.append("'"); + } + } else if (isStreamParam) { + if (quoteStreamsAndUnknowns) { + buf.append("'"); + } + + buf.append("** STREAM DATA **"); //$NON-NLS-1$ + + if (quoteStreamsAndUnknowns) { + buf.append("'"); + } } else { - if (this.charEncoding != null) { - buf.append(new String(this.parameterValues[i], - this.charEncoding)); + if (this.charConverter != null) { + buf.append(this.charConverter.toString(val)); } else { - buf.append(StringUtils - .toAsciiString(this.parameterValues[i])); + if (this.charEncoding != null) { + buf.append(new String(val, this.charEncoding)); + } else { + buf.append(StringUtils.toAsciiString(val)); + } } } } + + if (this.charEncoding != null) { + buf.append(StringUtils.toString( + this.staticSqlStrings[this.parameterCount + getParameterIndexOffset()], + this.charEncoding)); + } else { + buf + .append(StringUtils + .toAsciiString(this.staticSqlStrings[this.parameterCount + getParameterIndexOffset()])); + } + } catch (UnsupportedEncodingException uue) { + throw new RuntimeException(Messages + .getString("PreparedStatement.32") //$NON-NLS-1$ + + this.charEncoding + + Messages.getString("PreparedStatement.33")); //$NON-NLS-1$ } - - if (this.charEncoding != null) { - buf.append(new String( - this.staticSqlStrings[this.parameterCount], - this.charEncoding)); - } else { - buf - .append(StringUtils - .toAsciiString(this.staticSqlStrings[this.parameterCount])); - } - } catch (UnsupportedEncodingException uue) { - throw new RuntimeException(Messages - .getString("PreparedStatement.32") //$NON-NLS-1$ - + this.charEncoding - + Messages.getString("PreparedStatement.33")); //$NON-NLS-1$ + + return buf.toString(); } - - return buf.toString(); } - public synchronized void clearBatch() throws SQLException { - this.batchHasPlainStatements = false; - - super.clearBatch(); + public void clearBatch() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.batchHasPlainStatements = false; + + super.clearBatch(); + } } /** @@ -674,27 +1109,19 @@ * @exception SQLException * if a database access error occurs */ - public synchronized void clearParameters() throws SQLException { - checkClosed(); + public void clearParameters() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { - for (int i = 0; i < this.parameterValues.length; i++) { - this.parameterValues[i] = null; - this.parameterStreams[i] = null; - this.isStream[i] = false; - this.isNull[i] = false; + for (int i = 0; i < this.parameterValues.length; i++) { + this.parameterValues[i] = null; + this.parameterStreams[i] = null; + this.isStream[i] = false; + this.isNull[i] = false; + this.parameterTypes[i] = Types.NULL; + } } } - /** - * Closes this prepared statement and releases all resources. - * - * @throws SQLException - * if database error occurs. - */ - public synchronized void close() throws SQLException { - realClose(true, true); - } - private final void escapeblockFast(byte[] buf, Buffer packet, int size) throws SQLException { int lastwritten = 0; @@ -771,6 +1198,18 @@ bytesOut.write(buf, lastwritten, size - lastwritten); } } + + /** + * Check to see if the statement is safe for read-only slaves after failover. + * + * @return true if safe for read-only. + * @throws SQLException + */ + protected boolean checkReadOnlySafeStatement() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.firstCharOfStmt == 'S' || !this.connection.isReadOnly(); + } + } /** * Some prepared statements return multiple results; the execute method @@ -784,109 +1223,88 @@ * if a database access error occurs */ public boolean execute() throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - Connection locallyScopedConn = this.connection; - - if (locallyScopedConn.isReadOnly() && (this.firstCharOfStmt != 'S')) { - throw SQLError.createSQLException(Messages.getString("PreparedStatement.20") //$NON-NLS-1$ - + Messages.getString("PreparedStatement.21"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - ResultSet rs = null; - - CachedResultSetMetaData cachedMetadata = null; - - synchronized (locallyScopedConn.getMutex()) { + MySQLConnection locallyScopedConn = this.connection; + + if(!checkReadOnlySafeStatement()) { + throw SQLError.createSQLException(Messages.getString("PreparedStatement.20") //$NON-NLS-1$ + + Messages.getString("PreparedStatement.21"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + ResultSetInternalMethods rs = null; + + CachedResultSetMetaData cachedMetadata = null; + + lastQueryIsOnDupKeyUpdate = false; + + if (retrieveGeneratedKeys) { + lastQueryIsOnDupKeyUpdate = containsOnDuplicateKeyUpdateInSQL(); + } + + boolean doStreaming = createStreamingResultSet(); + clearWarnings(); - + + // Adjust net_write_timeout to a higher value if we're + // streaming result sets. More often than not, someone runs into + // an issue where they blow net_write_timeout when using this + // feature, and if they're willing to hold a result set open + // for 30 seconds or more, one more round-trip isn't going to hurt + // + // This is reset by RowDataDynamic.close(). + + if (doStreaming + && this.connection.getNetTimeoutForStreamingResults() > 0) { + executeSimpleNonQuery(locallyScopedConn, + "SET net_write_timeout=" + + this.connection + .getNetTimeoutForStreamingResults()); + } + this.batchedGeneratedKeys = null; - + Buffer sendPacket = fillSendPacket(); - + String oldCatalog = null; - + if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) { oldCatalog = locallyScopedConn.getCatalog(); locallyScopedConn.setCatalog(this.currentCatalog); } - + // // Check if we have cached metadata for this query... // if (locallyScopedConn.getCacheResultSetMetadata()) { cachedMetadata = locallyScopedConn.getCachedMetaData(this.originalSql); } - + Field[] metadataFromCache = null; if (cachedMetadata != null) { metadataFromCache = cachedMetadata.fields; } boolean oldInfoMsgState = false; - + if (this.retrieveGeneratedKeys) { oldInfoMsgState = locallyScopedConn.isReadInfoMsgEnabled(); locallyScopedConn.setReadInfoMsgEnabled(true); } - // If there isn't a limit clause in the SQL - // then limit the number of rows to return in - // an efficient manner. Only do this if - // setMaxRows() hasn't been used on any Statements - // generated from the current Connection (saves - // a query, and network traffic). // // Only apply max_rows to selects // - if (locallyScopedConn.useMaxRows()) { - int rowLimit = -1; + locallyScopedConn.setSessionMaxRows(this.firstCharOfStmt == 'S' ? this.maxRows : -1); - if (this.firstCharOfStmt == 'S') { - if (this.hasLimitClause) { - rowLimit = this.maxRows; - } else { - if (this.maxRows <= 0) { - locallyScopedConn.execSQL(this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, //$NON-NLS-1$ - null, java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.currentCatalog, true); - } else { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, -1, //$NON-NLS-1$ - null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.currentCatalog, - true); - } - } - } else { - locallyScopedConn.execSQL(this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$ - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.currentCatalog, true); - } + rs = executeInternal(this.maxRows, sendPacket, doStreaming, (this.firstCharOfStmt == 'S'), + metadataFromCache, false); - // Finally, execute the query - rs = executeInternal(rowLimit, sendPacket, - createStreamingResultSet(), - (this.firstCharOfStmt == 'S'), true, metadataFromCache, false); - } else { - rs = executeInternal(-1, sendPacket, - createStreamingResultSet(), - (this.firstCharOfStmt == 'S'), true, metadataFromCache, false); - } - if (cachedMetadata != null) { locallyScopedConn.initializeResultsMetadataFromCache(this.originalSql, - cachedMetadata, this.results); + cachedMetadata, rs); } else { if (rs.reallyResult() && locallyScopedConn.getCacheResultSetMetadata()) { locallyScopedConn.initializeResultsMetadataFromCache(this.originalSql, @@ -898,19 +1316,19 @@ locallyScopedConn.setReadInfoMsgEnabled(oldInfoMsgState); rs.setFirstCharOfQuery(this.firstCharOfStmt); } - + if (oldCatalog != null) { locallyScopedConn.setCatalog(oldCatalog); } - - this.lastInsertId = rs.getUpdateID(); - + if (rs != null) { + this.lastInsertId = rs.getUpdateID(); + this.results = rs; } + + return ((rs != null) && rs.reallyResult()); } - - return ((rs != null) && rs.reallyResult()); } /** @@ -928,352 +1346,682 @@ * DOCUMENT ME! */ public int[] executeBatch() throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (this.connection.isReadOnly()) { - throw new SQLException(Messages.getString("PreparedStatement.25") //$NON-NLS-1$ - + Messages.getString("PreparedStatement.26"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } + if (this.connection.isReadOnly()) { + throw new SQLException(Messages.getString("PreparedStatement.25") //$NON-NLS-1$ + + Messages.getString("PreparedStatement.26"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + } - synchronized (this.connection.getMutex()) { - if (this.batchedArgs == null || this.batchedArgs.size() == 0) { + if (this.batchedArgs == null || this.batchedArgs.size() == 0) { return new int[0]; } - + + // we timeout the entire batch, not individual statements + int batchTimeout = this.timeoutInMillis; + this.timeoutInMillis = 0; + + resetCancelledState(); + try { + statementBegins(); + clearWarnings(); if (!this.batchHasPlainStatements && this.connection.getRewriteBatchedStatements()) { - - if (canRewriteAsMultivalueInsertStatement()) { - return executeBatchedInserts(); + + + if (canRewriteAsMultiValueInsertAtSqlLevel()) { + return executeBatchedInserts(batchTimeout); } + + if (this.connection.versionMeetsMinimum(4, 1, 0) + && !this.batchHasPlainStatements + && this.batchedArgs != null + && this.batchedArgs.size() > 3 /* cost of option setting rt-wise */) { + return executePreparedBatchAsMultiStatement(batchTimeout); + } } - return executeBatchSerially(); - } catch (NullPointerException npe) { - // We do this, otherwise we need to totally overhaul how executeBatch() reuses - // existing execute() functionality, and pass around a locally-scoped connection, - // or catch the very rare race condition and handle it here. - - checkClosed(); // if we're really closed, this will throw a SQLException - - throw npe; // otherwise someone (me!) goofed error + return executeBatchSerially(batchTimeout); } finally { + this.statementExecuting.set(false); + clearBatch(); } } } - public synchronized boolean canRewriteAsMultivalueInsertStatement() { - if (!this.hasCheckedForRewrite) { - // Needs to be INSERT, can't have INSERT ... SELECT or - // INSERT ... ON DUPLICATE KEY UPDATE - // - // We're not smart enough to re-write to - // - // INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) - // ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b); - // - // (yet) - - this.canRewrite = StringUtils.startsWithIgnoreCaseAndWs( - this.originalSql, "INSERT", this.statementAfterCommentsPos) - && StringUtils.indexOfIgnoreCaseRespectMarker(this.statementAfterCommentsPos, this.originalSql, "SELECT", "\"'`", "\"'`", false) == -1 - && StringUtils.indexOfIgnoreCaseRespectMarker(this.statementAfterCommentsPos, this.originalSql, "UPDATE", "\"'`", "\"'`", false) == -1; - - this.hasCheckedForRewrite = true; - } - - return this.canRewrite; + public boolean canRewriteAsMultiValueInsertAtSqlLevel() throws SQLException { + return this.parseInfo.canRewriteAsMultiValueInsert; } + + protected int getLocationOfOnDuplicateKeyUpdate() throws SQLException { + return this.parseInfo.locationOfOnDuplicateKeyUpdate; + } /** - * Rewrites the already prepared statement into a multi-value insert - * statement of 'statementsPerBatch' values and executes the entire batch + * Rewrites the already prepared statement into a multi-statement + * query of 'statementsPerBatch' values and executes the entire batch * using this new statement. * * @return update counts in the same fashion as executeBatch() * * @throws SQLException */ - protected int[] executeBatchedInserts() throws SQLException { - String valuesClause = extractValuesClause(); + + protected int[] executePreparedBatchAsMultiStatement(int batchTimeout) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + // This is kind of an abuse, but it gets the job done + if (this.batchedValuesClause == null) { + this.batchedValuesClause = this.originalSql + ";"; + } + + MySQLConnection locallyScopedConn = this.connection; + + boolean multiQueriesEnabled = locallyScopedConn.getAllowMultiQueries(); + CancelTask timeoutTask = null; + + try { + clearWarnings(); + + int numBatchedArgs = this.batchedArgs.size(); + + if (this.retrieveGeneratedKeys) { + this.batchedGeneratedKeys = new ArrayList(numBatchedArgs); + } - Connection locallyScopedConn = this.connection; - - if (valuesClause == null) { - return executeBatchSerially(); - } + int numValuesPerBatch = computeBatchSize(numBatchedArgs); - int numBatchedArgs = this.batchedArgs.size(); - - if (this.retrieveGeneratedKeys) { - this.batchedGeneratedKeys = new ArrayList(numBatchedArgs); - } + if (numBatchedArgs < numValuesPerBatch) { + numValuesPerBatch = numBatchedArgs; + } - int numValuesPerBatch = computeBatchSize(numBatchedArgs); + java.sql.PreparedStatement batchedStatement = null; - if (numBatchedArgs < numValuesPerBatch) { - numValuesPerBatch = numBatchedArgs; - } + int batchedParamIndex = 1; + int numberToExecuteAsMultiValue = 0; + int batchCounter = 0; + int updateCountCounter = 0; + int[] updateCounts = new int[numBatchedArgs]; + SQLException sqlEx = null; + + try { + if (!multiQueriesEnabled) { + locallyScopedConn.getIO().enableMultiQueries(); + } + + if (this.retrieveGeneratedKeys) { + batchedStatement = locallyScopedConn.prepareStatement( + generateMultiStatementForBatch(numValuesPerBatch), + RETURN_GENERATED_KEYS); + } else { + batchedStatement = locallyScopedConn + .prepareStatement(generateMultiStatementForBatch(numValuesPerBatch)); + } - java.sql.PreparedStatement batchedStatement = null; + if (locallyScopedConn.getEnableQueryTimeouts() && + batchTimeout != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask((StatementImpl)batchedStatement); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + batchTimeout); + } + + if (numBatchedArgs < numValuesPerBatch) { + numberToExecuteAsMultiValue = numBatchedArgs; + } else { + numberToExecuteAsMultiValue = numBatchedArgs / numValuesPerBatch; + } + + int numberArgsToExecute = numberToExecuteAsMultiValue * numValuesPerBatch; + + for (int i = 0; i < numberArgsToExecute; i++) { + if (i != 0 && i % numValuesPerBatch == 0) { + try { + batchedStatement.execute(); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(batchCounter, numValuesPerBatch, + updateCounts, ex); + } + + updateCountCounter = processMultiCountsAndKeys( + (StatementImpl)batchedStatement, updateCountCounter, + updateCounts); + + batchedStatement.clearParameters(); + batchedParamIndex = 1; + } + + batchedParamIndex = setOneBatchedParameterSet(batchedStatement, + batchedParamIndex, this.batchedArgs + .get(batchCounter++)); + } + + try { + batchedStatement.execute(); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(batchCounter - 1, numValuesPerBatch, + updateCounts, ex); + } + + updateCountCounter = processMultiCountsAndKeys( + (StatementImpl)batchedStatement, updateCountCounter, + updateCounts); + + batchedStatement.clearParameters(); + + numValuesPerBatch = numBatchedArgs - batchCounter; + } finally { + if (batchedStatement != null) { + batchedStatement.close(); + batchedStatement = null; + } + } + + try { + if (numValuesPerBatch > 0) { + + if (this.retrieveGeneratedKeys) { + batchedStatement = locallyScopedConn.prepareStatement( + generateMultiStatementForBatch(numValuesPerBatch), + RETURN_GENERATED_KEYS); + } else { + batchedStatement = locallyScopedConn.prepareStatement( + generateMultiStatementForBatch(numValuesPerBatch)); + } + + if (timeoutTask != null) { + timeoutTask.toCancel = (StatementImpl)batchedStatement; + } + + batchedParamIndex = 1; + + while (batchCounter < numBatchedArgs) { + batchedParamIndex = setOneBatchedParameterSet(batchedStatement, + batchedParamIndex, this.batchedArgs + .get(batchCounter++)); + } + + try { + batchedStatement.execute(); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(batchCounter - 1, numValuesPerBatch, + updateCounts, ex); + } + + updateCountCounter = processMultiCountsAndKeys( + (StatementImpl)batchedStatement, updateCountCounter, + updateCounts); + + batchedStatement.clearParameters(); + } + + if (timeoutTask != null) { + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } - int batchedParamIndex = 1; - int updateCountRunningTotal = 0; - int numberToExecuteAsMultiValue = 0; - int batchCounter = 0; - - try { - if (this.retrieveGeneratedKeys) { - batchedStatement = locallyScopedConn.prepareStatement( - generateBatchedInsertSQL(valuesClause, numValuesPerBatch), - RETURN_GENERATED_KEYS); - } else { - batchedStatement = locallyScopedConn - .prepareStatement(generateBatchedInsertSQL(valuesClause, - numValuesPerBatch)); + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + + timeoutTask = null; + } + + if (sqlEx != null) { + SQLException batchUpdateException = new java.sql.BatchUpdateException(sqlEx + .getMessage(), sqlEx.getSQLState(), sqlEx + .getErrorCode(), updateCounts); + batchUpdateException.initCause(sqlEx); + throw batchUpdateException; + } + + return updateCounts; + } finally { + if (batchedStatement != null) { + batchedStatement.close(); + } + } + } finally { + if (timeoutTask != null) { + timeoutTask.cancel(); + locallyScopedConn.getCancelTimer().purge(); + } + + resetCancelledState(); + + if (!multiQueriesEnabled) { + locallyScopedConn.getIO().disableMultiQueries(); + } + + clearBatch(); } - - if (numBatchedArgs < numValuesPerBatch) { - numberToExecuteAsMultiValue = numBatchedArgs; - } else { - numberToExecuteAsMultiValue = numBatchedArgs / numValuesPerBatch; + } + } + + private String generateMultiStatementForBatch(int numBatches) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + StringBuffer newStatementSql = new StringBuffer((this.originalSql + .length() + 1) * numBatches); + + newStatementSql.append(this.originalSql); + + for (int i = 0; i < numBatches - 1; i++) { + newStatementSql.append(';'); + newStatementSql.append(this.originalSql); } - int numberArgsToExecute = numberToExecuteAsMultiValue * numValuesPerBatch; + return newStatementSql.toString(); + } + } - for (int i = 0; i < numberArgsToExecute; i++) { - if (i != 0 && i % numValuesPerBatch == 0) { - updateCountRunningTotal += batchedStatement.executeUpdate(); + /** + * Rewrites the already prepared statement into a multi-value insert + * statement of 'statementsPerBatch' values and executes the entire batch + * using this new statement. + * + * @return update counts in the same fashion as executeBatch() + * + * @throws SQLException + */ + protected int[] executeBatchedInserts(int batchTimeout) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + String valuesClause = getValuesClause(); - getBatchedGeneratedKeys(batchedStatement); - batchedStatement.clearParameters(); - batchedParamIndex = 1; + MySQLConnection locallyScopedConn = this.connection; - } + if (valuesClause == null) { + return executeBatchSerially(batchTimeout); + } - batchedParamIndex = setOneBatchedParameterSet(batchedStatement, - batchedParamIndex, this.batchedArgs - .get(batchCounter++)); + int numBatchedArgs = this.batchedArgs.size(); + + if (this.retrieveGeneratedKeys) { + this.batchedGeneratedKeys = new ArrayList(numBatchedArgs); } - updateCountRunningTotal += batchedStatement.executeUpdate(); - getBatchedGeneratedKeys(batchedStatement); + int numValuesPerBatch = computeBatchSize(numBatchedArgs); - numValuesPerBatch = numBatchedArgs - batchCounter; - } finally { - if (batchedStatement != null) { - batchedStatement.close(); + if (numBatchedArgs < numValuesPerBatch) { + numValuesPerBatch = numBatchedArgs; } - } - - try { - if (numValuesPerBatch > 0) { - if (this.retrieveGeneratedKeys) { - batchedStatement = locallyScopedConn.prepareStatement( - generateBatchedInsertSQL(valuesClause, numValuesPerBatch), - RETURN_GENERATED_KEYS); - } else { - batchedStatement = locallyScopedConn.prepareStatement( - generateBatchedInsertSQL(valuesClause, numValuesPerBatch)); - } - - batchedParamIndex = 1; + java.sql.PreparedStatement batchedStatement = null; - while (batchCounter < numBatchedArgs) { - batchedParamIndex = setOneBatchedParameterSet(batchedStatement, - batchedParamIndex, this.batchedArgs - .get(batchCounter++)); + int batchedParamIndex = 1; + int updateCountRunningTotal = 0; + int numberToExecuteAsMultiValue = 0; + int batchCounter = 0; + CancelTask timeoutTask = null; + SQLException sqlEx = null; + + int[] updateCounts = new int[numBatchedArgs]; + + try { + try { + batchedStatement = /* FIXME -if we ever care about folks proxying our MySQLConnection */ + prepareBatchedInsertSQL(locallyScopedConn, numValuesPerBatch); + + if (locallyScopedConn.getEnableQueryTimeouts() + && batchTimeout != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask( + (StatementImpl) batchedStatement); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + batchTimeout); + } + + if (numBatchedArgs < numValuesPerBatch) { + numberToExecuteAsMultiValue = numBatchedArgs; + } else { + numberToExecuteAsMultiValue = numBatchedArgs + / numValuesPerBatch; + } + + int numberArgsToExecute = numberToExecuteAsMultiValue + * numValuesPerBatch; + + for (int i = 0; i < numberArgsToExecute; i++) { + if (i != 0 && i % numValuesPerBatch == 0) { + try { + updateCountRunningTotal += batchedStatement + .executeUpdate(); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(batchCounter - 1, + numValuesPerBatch, updateCounts, ex); + } + + getBatchedGeneratedKeys(batchedStatement); + batchedStatement.clearParameters(); + batchedParamIndex = 1; + + } + + batchedParamIndex = setOneBatchedParameterSet( + batchedStatement, batchedParamIndex, + this.batchedArgs.get(batchCounter++)); + } + + try { + updateCountRunningTotal += + batchedStatement.executeUpdate(); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(batchCounter - 1, + numValuesPerBatch, updateCounts, ex); + } + + getBatchedGeneratedKeys(batchedStatement); + + numValuesPerBatch = numBatchedArgs - batchCounter; + } finally { + if (batchedStatement != null) { + batchedStatement.close(); + batchedStatement = null; + } } - updateCountRunningTotal += batchedStatement.executeUpdate(); - getBatchedGeneratedKeys(batchedStatement); - } + try { + if (numValuesPerBatch > 0) { + batchedStatement = + prepareBatchedInsertSQL(locallyScopedConn, + numValuesPerBatch); + + if (timeoutTask != null) { + timeoutTask.toCancel = (StatementImpl) batchedStatement; + } - int[] updateCounts = new int[this.batchedArgs.size()]; + batchedParamIndex = 1; - for (int i = 0; i < this.batchedArgs.size(); i++) { - updateCounts[i] = 1; - } + while (batchCounter < numBatchedArgs) { + batchedParamIndex = setOneBatchedParameterSet( + batchedStatement, batchedParamIndex, + this.batchedArgs.get(batchCounter++)); + } - return updateCounts; - } finally { - if (batchedStatement != null) { - batchedStatement.close(); + try { + updateCountRunningTotal += batchedStatement.executeUpdate(); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(batchCounter - 1, + numValuesPerBatch, updateCounts, ex); + } + + getBatchedGeneratedKeys(batchedStatement); + } + + if (sqlEx != null) { + SQLException batchUpdateException = new java.sql.BatchUpdateException(sqlEx + .getMessage(), sqlEx.getSQLState(), sqlEx + .getErrorCode(), updateCounts); + batchUpdateException.initCause(sqlEx); + throw batchUpdateException; + } + + if (numBatchedArgs > 1) { + int updCount = updateCountRunningTotal > 0 ? Statement.SUCCESS_NO_INFO : 0; + for (int j = 0; j < numBatchedArgs; j++) { + updateCounts[j] = updCount; + } + } else { + updateCounts[0] = updateCountRunningTotal; + } + return updateCounts; + } finally { + if (batchedStatement != null) { + batchedStatement.close(); + } + } + } finally { + if (timeoutTask != null) { + timeoutTask.cancel(); + locallyScopedConn.getCancelTimer().purge(); + } + + resetCancelledState(); } } } + protected String getValuesClause() throws SQLException { + return this.parseInfo.valuesClause; + } + /** * Computes the optimum number of batched parameter lists to send * without overflowing max_allowed_packet. * * @param numBatchedArgs * @return + * @throws SQLException */ - protected int computeBatchSize(int numBatchedArgs) { - long[] combinedValues = computeMaxParameterSetSizeAndBatchSize(numBatchedArgs); - - long maxSizeOfParameterSet = combinedValues[0]; - long sizeOfEntireBatch = combinedValues[1]; - - int maxAllowedPacket = this.connection.getMaxAllowedPacket(); - - if (sizeOfEntireBatch < maxAllowedPacket - this.originalSql.length()) { - return numBatchedArgs; + protected int computeBatchSize(int numBatchedArgs) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + long[] combinedValues = computeMaxParameterSetSizeAndBatchSize(numBatchedArgs); + + long maxSizeOfParameterSet = combinedValues[0]; + long sizeOfEntireBatch = combinedValues[1]; + + int maxAllowedPacket = this.connection.getMaxAllowedPacket(); + + if (sizeOfEntireBatch < maxAllowedPacket - this.originalSql.length()) { + return numBatchedArgs; + } + + return (int)Math.max(1, (maxAllowedPacket - this.originalSql.length()) / maxSizeOfParameterSet); } - - return (int)Math.max(1, (maxAllowedPacket - this.originalSql.length()) / maxSizeOfParameterSet); } - + /** * Computes the maximum parameter set size, and entire batch size given * the number of arguments in the batch. + * @throws SQLException */ - protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) { - long sizeOfEntireBatch = 0; - long maxSizeOfParameterSet = 0; - - for (int i = 0; i < numBatchedArgs; i++) { - BatchParams paramArg = (BatchParams) this.batchedArgs - .get(i); - - boolean[] isNullBatch = paramArg.isNull; - boolean[] isStreamBatch = paramArg.isStream; - - long sizeOfParameterSet = 0; + protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + long sizeOfEntireBatch = 0; + long maxSizeOfParameterSet = 0; - for (int j = 0; j < isNullBatch.length; j++) { - if (!isNullBatch[j]) { - - if (isStreamBatch[j]) { - int streamLength = paramArg.streamLengths[j]; - - if (streamLength != -1) { - sizeOfParameterSet += streamLength * 2; // for safety in escaping + for (int i = 0; i < numBatchedArgs; i++) { + BatchParams paramArg = (BatchParams) this.batchedArgs + .get(i); + + boolean[] isNullBatch = paramArg.isNull; + boolean[] isStreamBatch = paramArg.isStream; + + long sizeOfParameterSet = 0; + + for (int j = 0; j < isNullBatch.length; j++) { + if (!isNullBatch[j]) { + + if (isStreamBatch[j]) { + int streamLength = paramArg.streamLengths[j]; + + if (streamLength != -1) { + sizeOfParameterSet += streamLength * 2; // for safety in escaping + } else { + int paramLength = paramArg.parameterStrings[j].length; + sizeOfParameterSet += paramLength; + } + } else { + sizeOfParameterSet += paramArg.parameterStrings[j].length; } } else { - sizeOfParameterSet += paramArg.parameterStrings[j].length; + sizeOfParameterSet += 4; // for NULL literal in SQL } + } + + // + // Account for static part of values clause + // This is a little naiive, because the ?s will be replaced + // but it gives us some padding, and is less housekeeping + // to ignore them. We're looking for a "fuzzy" value here + // anyway + // + + if (getValuesClause() != null) { + sizeOfParameterSet += getValuesClause().length() + 1; } else { - sizeOfParameterSet += 4; // for NULL literal in SQL + sizeOfParameterSet += this.originalSql.length() + 1; } - } + + sizeOfEntireBatch += sizeOfParameterSet; + + if (sizeOfParameterSet > maxSizeOfParameterSet) { + maxSizeOfParameterSet = sizeOfParameterSet; + } + } - // - // Account for static part of values clause - // This is a little naiive, because the ?s will be replaced - // but it gives us some padding, and is less housekeeping - // to ignore them. We're looking for a "fuzzy" value here - // anyway - // - - sizeOfParameterSet += this.batchedValuesClause.length() + 1; - sizeOfEntireBatch += sizeOfParameterSet; - - if (sizeOfParameterSet > maxSizeOfParameterSet) { - maxSizeOfParameterSet = sizeOfParameterSet; - } - } - - return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch}; + return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch}; + } } + /** * Executes the current batch of statements by executing them one-by-one. * * @return a list of update counts * @throws SQLException * if an error occurs */ - protected int[] executeBatchSerially() throws SQLException { + protected int[] executeBatchSerially(int batchTimeout) throws SQLException { - Connection locallyScopedConn = this.connection; - - if (locallyScopedConn == null) { - checkClosed(); - } - - int[] updateCounts = null; - - if (this.batchedArgs != null) { - int nbrCommands = this.batchedArgs.size(); - updateCounts = new int[nbrCommands]; - - for (int i = 0; i < nbrCommands; i++) { - updateCounts[i] = -3; + synchronized (checkClosed().getConnectionMutex()) { + MySQLConnection locallyScopedConn = this.connection; + + if (locallyScopedConn == null) { + checkClosed(); } - - SQLException sqlEx = null; - - int commandIndex = 0; - - if (this.retrieveGeneratedKeys) { - this.batchedGeneratedKeys = new ArrayList(nbrCommands); - } - - for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { - Object arg = this.batchedArgs.get(commandIndex); - - if (arg instanceof String) { - updateCounts[commandIndex] = executeUpdate((String) arg); - } else { - BatchParams paramArg = (BatchParams) arg; - - try { - updateCounts[commandIndex] = executeUpdate( - paramArg.parameterStrings, - paramArg.parameterStreams, paramArg.isStream, - paramArg.streamLengths, paramArg.isNull, true); - - if (this.retrieveGeneratedKeys) { - java.sql.ResultSet rs = null; - + + int[] updateCounts = null; + + if (this.batchedArgs != null) { + int nbrCommands = this.batchedArgs.size(); + updateCounts = new int[nbrCommands]; + + for (int i = 0; i < nbrCommands; i++) { + updateCounts[i] = -3; + } + + SQLException sqlEx = null; + + CancelTask timeoutTask = null; + + try { + if (locallyScopedConn.getEnableQueryTimeouts() && + batchTimeout != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + batchTimeout); + } + + if (this.retrieveGeneratedKeys) { + this.batchedGeneratedKeys = new ArrayList(nbrCommands); + } + + for (batchCommandIndex = 0; batchCommandIndex < nbrCommands; batchCommandIndex++) { + Object arg = this.batchedArgs.get(batchCommandIndex); + + if (arg instanceof String) { + updateCounts[batchCommandIndex] = executeUpdate((String) arg); + } else { + BatchParams paramArg = (BatchParams) arg; + try { - rs = getGeneratedKeysInternal(); - - while (rs.next()) { - this.batchedGeneratedKeys - .add(new byte[][] { rs.getBytes(1) }); + updateCounts[batchCommandIndex] = executeUpdate( + paramArg.parameterStrings, + paramArg.parameterStreams, paramArg.isStream, + paramArg.streamLengths, paramArg.isNull, true); + + if (this.retrieveGeneratedKeys) { + java.sql.ResultSet rs = null; + + try { + if (containsOnDuplicateKeyUpdateInSQL()) + rs = getGeneratedKeysInternal(1); + else + rs = getGeneratedKeysInternal(); + + while (rs.next()) { + this.batchedGeneratedKeys + .add(new ByteArrayRow(new byte[][] { rs.getBytes(1) }, getExceptionInterceptor())); + } + } finally { + if (rs != null) { + rs.close(); + } + } } - } finally { - if (rs != null) { - rs.close(); + } catch (SQLException ex) { + updateCounts[batchCommandIndex] = EXECUTE_FAILED; + + if (this.continueBatchOnError && + !(ex instanceof MySQLTimeoutException) && + !(ex instanceof MySQLStatementCancelledException) && + !hasDeadlockOrTimeoutRolledBackTx(ex)) { + sqlEx = ex; + } else { + int[] newUpdateCounts = new int[batchCommandIndex]; + System.arraycopy(updateCounts, 0, + newUpdateCounts, 0, batchCommandIndex); + + SQLException batchUpdateException = new java.sql.BatchUpdateException(ex + .getMessage(), ex.getSQLState(), ex + .getErrorCode(), newUpdateCounts); + batchUpdateException.initCause(ex); + throw batchUpdateException; } } } - } catch (SQLException ex) { - updateCounts[commandIndex] = EXECUTE_FAILED; - - if (this.continueBatchOnError) { - sqlEx = ex; - } else { - int[] newUpdateCounts = new int[commandIndex]; - System.arraycopy(updateCounts, 0, newUpdateCounts, - 0, commandIndex); - - throw new java.sql.BatchUpdateException(ex - .getMessage(), ex.getSQLState(), ex - .getErrorCode(), newUpdateCounts); - } } + + if (sqlEx != null) { + SQLException batchUpdateException = new java.sql.BatchUpdateException(sqlEx.getMessage(), + sqlEx.getSQLState(), sqlEx.getErrorCode(), updateCounts); + batchUpdateException.initCause(sqlEx); + throw batchUpdateException; + } + } catch (NullPointerException npe) { + try { + checkClosed(); + } catch (SQLException connectionClosedEx) { + updateCounts[batchCommandIndex] = EXECUTE_FAILED; + + int[] newUpdateCounts = new int[batchCommandIndex]; + + System.arraycopy(updateCounts, 0, + newUpdateCounts, 0, batchCommandIndex); + + throw new java.sql.BatchUpdateException(connectionClosedEx + .getMessage(), connectionClosedEx.getSQLState(), connectionClosedEx + .getErrorCode(), newUpdateCounts); + } + + throw npe; // we don't know why this happened, punt + } finally { + batchCommandIndex = -1; + + if (timeoutTask != null) { + timeoutTask.cancel(); + locallyScopedConn.getCancelTimer().purge(); + } + + resetCancelledState(); } } - - if (sqlEx != null) { - throw new java.sql.BatchUpdateException(sqlEx.getMessage(), - sqlEx.getSQLState(), sqlEx.getErrorCode(), updateCounts); - } + + return (updateCounts != null) ? updateCounts : new int[0]; } - - return (updateCounts != null) ? updateCounts : new int[0]; + } + public String getDateTime(String pattern){ + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + return sdf.format(new java.util.Date()); + } + /** * Actually execute the prepared statement. This is here so server-side * PreparedStatements can re-use most of the code from this class. @@ -1294,75 +2042,94 @@ * @throws SQLException * if an error occurs. */ - protected ResultSet executeInternal(int maxRowsToRetrieve, + protected ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, - boolean queryIsSelectOnly, boolean unpackFields, Field[] cachedFields, + boolean queryIsSelectOnly, Field[] metadataFromCache, boolean isBatch) throws SQLException { - try { - - - synchronized (this.cancelTimeoutMutex) { - this.wasCancelled = false; - } - - Connection locallyScopedConnection= this.connection; - - this.numberOfExecutions++; - - if (this.doPingInstead) { - doPingInstead(); - - return this.results; - } - - ResultSet rs; - - CancelTask timeoutTask = null; - + synchronized (checkClosed().getConnectionMutex()) { try { - if (locallyScopedConnection.getEnableQueryTimeouts() && - this.timeoutInMillis != 0 - && locallyScopedConnection.versionMeetsMinimum(5, 0, 0)) { - timeoutTask = new CancelTask(); - Connection.getCancelTimer().schedule(timeoutTask, - this.timeoutInMillis); + + resetCancelledState(); + + MySQLConnection locallyScopedConnection = this.connection; + + this.numberOfExecutions++; + + if (this.doPingInstead) { + doPingInstead(); + + return this.results; } - rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket, - this.resultSetType, this.resultSetConcurrency, - createStreamingResultSet, this.currentCatalog, - unpackFields, isBatch); + ResultSetInternalMethods rs; - if (timeoutTask != null) { - timeoutTask.cancel(); + CancelTask timeoutTask = null; + + try { + if (locallyScopedConnection.getEnableQueryTimeouts() && + this.timeoutInMillis != 0 + && locallyScopedConnection.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConnection.getCancelTimer().schedule(timeoutTask, + this.timeoutInMillis); + } + + if (!isBatch) { + statementBegins(); + } - if (timeoutTask.caughtWhileCancelling != null) { - throw timeoutTask.caughtWhileCancelling; + rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket, + this.resultSetType, this.resultSetConcurrency, + createStreamingResultSet, this.currentCatalog, + metadataFromCache, isBatch); + + if (timeoutTask != null) { + timeoutTask.cancel(); + + locallyScopedConnection.getCancelTimer().purge(); + + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } + + timeoutTask = null; } + + synchronized (this.cancelTimeoutMutex) { + if (this.wasCancelled) { + SQLException cause = null; + + if (this.wasCancelledByTimeout) { + cause = new MySQLTimeoutException(); + } else { + cause = new MySQLStatementCancelledException(); + } + + resetCancelledState(); + + throw cause; + } + } + } finally { + if (!isBatch) { + this.statementExecuting.set(false); + } - timeoutTask = null; - } - - synchronized (this.cancelTimeoutMutex) { - if (this.wasCancelled) { - this.wasCancelled = false; - throw new MySQLTimeoutException(); + if (timeoutTask != null) { + timeoutTask.cancel(); + locallyScopedConnection.getCancelTimer().purge(); } } - } finally { - if (timeoutTask != null) { - timeoutTask.cancel(); - } + + return rs; + } catch (NullPointerException npe) { + checkClosed(); // we can't synchronize ourselves against async connection-close + // due to deadlock issues, so this is the next best thing for + // this particular corner case. + + throw npe; } - - return rs; - } catch (NullPointerException npe) { - checkClosed(); // we can't synchronize ourselves against async connection-close - // due to deadlock issues, so this is the next best thing for - // this particular corner case. - - throw npe; } } @@ -1376,33 +2143,50 @@ * if a database access error occurs */ public java.sql.ResultSet executeQuery() throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - Connection locallyScopedConn = this.connection; - - checkForDml(this.originalSql, this.firstCharOfStmt); + MySQLConnection locallyScopedConn = this.connection; + + checkForDml(this.originalSql, this.firstCharOfStmt); + + CachedResultSetMetaData cachedMetadata = null; + - CachedResultSetMetaData cachedMetadata = null; - - // We need to execute this all together - // So synchronize on the Connection's mutex (because - // even queries going through there synchronize - // on the same mutex. - synchronized (locallyScopedConn.getMutex()) { clearWarnings(); + boolean doStreaming = createStreamingResultSet(); + this.batchedGeneratedKeys = null; - Buffer sendPacket = fillSendPacket(); - - if (this.results != null) { - if (!this.connection.getHoldResultsOpenOverStatementClose()) { - if (!this.holdResultsOpenOverClose) { - this.results.realClose(false); + // Adjust net_write_timeout to a higher value if we're + // streaming result sets. More often than not, someone runs into + // an issue where they blow net_write_timeout when using this + // feature, and if they're willing to hold a result set open + // for 30 seconds or more, one more round-trip isn't going to hurt + // + // This is reset by RowDataDynamic.close(). + + if (doStreaming + && this.connection.getNetTimeoutForStreamingResults() > 0) { + + java.sql.Statement stmt = null; + + try { + stmt = this.connection.createStatement(); + + ((com.mysql.jdbc.StatementImpl)stmt).executeSimpleNonQuery(this.connection, "SET net_write_timeout=" + + this.connection.getNetTimeoutForStreamingResults()); + } finally { + if (stmt != null) { + stmt.close(); } } } + + Buffer sendPacket = fillSendPacket(); + implicitlyCloseAllOpenResults(); + String oldCatalog = null; if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) { @@ -1422,52 +2206,10 @@ if (cachedMetadata != null) { metadataFromCache = cachedMetadata.fields; } - - if (locallyScopedConn.useMaxRows()) { - // If there isn't a limit clause in the SQL - // then limit the number of rows to return in - // an efficient manner. Only do this if - // setMaxRows() hasn't been used on any Statements - // generated from the current Connection (saves - // a query, and network traffic). - if (this.hasLimitClause) { - this.results = executeInternal(this.maxRows, sendPacket, - createStreamingResultSet(), true, - (cachedMetadata == null), metadataFromCache, false); - } else { - if (this.maxRows <= 0) { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$ - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.currentCatalog, true); - } else { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, -1, null, //$NON-NLS-1$ - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.currentCatalog, true); - } - - - this.results = executeInternal(-1, sendPacket, - createStreamingResultSet(), true, - (cachedMetadata == null), metadataFromCache, false); + locallyScopedConn.setSessionMaxRows(this.maxRows); - if (oldCatalog != null) { - this.connection.setCatalog(oldCatalog); - } - } - } else { - this.results = executeInternal(-1, sendPacket, - createStreamingResultSet(), true, - (cachedMetadata == null), metadataFromCache, false); - } + this.results = executeInternal(this.maxRows, sendPacket, doStreaming, true, metadataFromCache, false); if (oldCatalog != null) { locallyScopedConn.setCatalog(oldCatalog); @@ -1482,13 +2224,13 @@ null /* will be created */, this.results); } } - } - this.lastInsertId = this.results.getUpdateID(); - - return this.results; + this.lastInsertId = this.results.getUpdateID(); + + return this.results; + } } - + /** * Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL * statements that return nothing such as SQL DDL statements can be @@ -1511,13 +2253,15 @@ */ protected int executeUpdate( boolean clearBatchedGeneratedKeysAndWarnings, boolean isBatch) throws SQLException { - if (clearBatchedGeneratedKeysAndWarnings) { - clearWarnings(); - this.batchedGeneratedKeys = null; + synchronized (checkClosed().getConnectionMutex()) { + if (clearBatchedGeneratedKeysAndWarnings) { + clearWarnings(); + this.batchedGeneratedKeys = null; + } + + return executeUpdate(this.parameterValues, this.parameterStreams, + this.isStream, this.streamLengths, this.isNull, isBatch); } - - return executeUpdate(this.parameterValues, this.parameterStreams, - this.isStream, this.streamLengths, this.isNull, isBatch); } /** @@ -1544,34 +2288,26 @@ int[] batchedStreamLengths, boolean[] batchedIsNull, boolean isReallyBatch) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - Connection locallyScopedConn = this.connection; - - if (locallyScopedConn.isReadOnly()) { - throw SQLError.createSQLException(Messages.getString("PreparedStatement.34") //$NON-NLS-1$ - + Messages.getString("PreparedStatement.35"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - if ((this.firstCharOfStmt == 'S') - && isSelectQuery()) { //$NON-NLS-1$ - throw SQLError.createSQLException(Messages.getString("PreparedStatement.37"), //$NON-NLS-1$ - "01S03"); //$NON-NLS-1$ - } - - if (this.results != null) { - if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) { - this.results.realClose(false); + MySQLConnection locallyScopedConn = this.connection; + + if (locallyScopedConn.isReadOnly()) { + throw SQLError.createSQLException(Messages.getString("PreparedStatement.34") //$NON-NLS-1$ + + Messages.getString("PreparedStatement.35"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } - } + + if ((this.firstCharOfStmt == 'S') + && isSelectQuery()) { //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("PreparedStatement.37"), //$NON-NLS-1$ + "01S03", getExceptionInterceptor()); //$NON-NLS-1$ + } + + implicitlyCloseAllOpenResults(); - ResultSet rs = null; + ResultSetInternalMethods rs = null; - // The checking and changing of catalogs - // must happen in sequence, so synchronize - // on the same mutex that _conn is using - synchronized (locallyScopedConn.getMutex()) { Buffer sendPacket = fillSendPacket(batchedParameterStrings, batchedParameterStreams, batchedIsStream, batchedStreamLengths); @@ -1586,13 +2322,7 @@ // // Only apply max_rows to selects // - if (locallyScopedConn.useMaxRows()) { - locallyScopedConn.execSQL(this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$ - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.currentCatalog, true); - } + locallyScopedConn.setSessionMaxRows(-1); boolean oldInfoMsgState = false; @@ -1601,7 +2331,7 @@ locallyScopedConn.setReadInfoMsgEnabled(true); } - rs = executeInternal(-1, sendPacket, false, false, true, null, + rs = executeInternal(-1, sendPacket, false, false, null, isReallyBatch); if (this.retrieveGeneratedKeys) { @@ -1612,66 +2342,36 @@ if (oldCatalog != null) { locallyScopedConn.setCatalog(oldCatalog); } - } - this.results = rs; - - this.updateCount = rs.getUpdateCount(); - - int truncatedUpdateCount = 0; - - if (this.updateCount > Integer.MAX_VALUE) { - truncatedUpdateCount = Integer.MAX_VALUE; - } else { - truncatedUpdateCount = (int) this.updateCount; - } - - this.lastInsertId = rs.getUpdateID(); - - return truncatedUpdateCount; - } - - private String extractValuesClause() throws SQLException { - if (this.batchedValuesClause == null) { - String quoteCharStr = this.connection.getMetaData() - .getIdentifierQuoteString(); + this.results = rs; - int indexOfValues = -1; - - if (quoteCharStr.length() > 0) { - indexOfValues = StringUtils.indexOfIgnoreCaseRespectQuotes( - this.statementAfterCommentsPos, - this.originalSql, "VALUES ", quoteCharStr.charAt(0), false); - } else { - indexOfValues = StringUtils.indexOfIgnoreCase(this.statementAfterCommentsPos, - this.originalSql, - "VALUES "); + this.updateCount = rs.getUpdateCount(); + + if (containsOnDuplicateKeyUpdateInSQL() && + this.compensateForOnDuplicateKeyUpdate) { + if (this.updateCount == 2 || this.updateCount == 0) { + this.updateCount = 1; + } } - if (indexOfValues == -1) { - return null; - } + int truncatedUpdateCount = 0; - int indexOfFirstParen = this.originalSql - .indexOf('(', indexOfValues + 7); - - if (indexOfFirstParen == -1) { - return null; + if (this.updateCount > Integer.MAX_VALUE) { + truncatedUpdateCount = Integer.MAX_VALUE; + } else { + truncatedUpdateCount = (int) this.updateCount; } - int indexOfLastParen = this.originalSql.lastIndexOf(')'); + this.lastInsertId = rs.getUpdateID(); - if (indexOfLastParen == -1) { - return null; - } - - this.batchedValuesClause = this.originalSql.substring(indexOfFirstParen, - indexOfLastParen + 1); + return truncatedUpdateCount; } - - return this.batchedValuesClause; } + protected boolean containsOnDuplicateKeyUpdateInSQL() { + return this.parseInfo.isOnDuplicateKeyUpdate; + } + /** * Creates the packet that contains the query to be sent to the server. * @@ -1682,8 +2382,10 @@ * if an error occurs. */ protected Buffer fillSendPacket() throws SQLException { - return fillSendPacket(this.parameterValues, this.parameterStreams, - this.isStream, this.streamLengths); + synchronized (checkClosed().getConnectionMutex()) { + return fillSendPacket(this.parameterValues, this.parameterStreams, + this.isStream, this.streamLengths); + } } /** @@ -1706,70 +2408,126 @@ protected Buffer fillSendPacket(byte[][] batchedParameterStrings, InputStream[] batchedParameterStreams, boolean[] batchedIsStream, int[] batchedStreamLengths) throws SQLException { - Buffer sendPacket = this.connection.getIO().getSharedSendPacket(); - - sendPacket.clear(); - - sendPacket.writeByte((byte) MysqlDefs.QUERY); - - boolean useStreamLengths = this.connection - .getUseStreamLengthsInPrepStmts(); - - // - // Try and get this allocation as close as possible - // for BLOBs - // - int ensurePacketSize = 0; - - for (int i = 0; i < batchedParameterStrings.length; i++) { - if (batchedIsStream[i] && useStreamLengths) { - ensurePacketSize += batchedStreamLengths[i]; + synchronized (checkClosed().getConnectionMutex()) { + Buffer sendPacket = this.connection.getIO().getSharedSendPacket(); + + sendPacket.clear(); + + sendPacket.writeByte((byte) MysqlDefs.QUERY); + + boolean useStreamLengths = this.connection + .getUseStreamLengthsInPrepStmts(); + + // + // Try and get this allocation as close as possible + // for BLOBs + // + int ensurePacketSize = 0; + + String statementComment = this.connection.getStatementComment(); + + byte[] commentAsBytes = null; + + if (statementComment != null) { + if (this.charConverter != null) { + commentAsBytes = this.charConverter.toBytes(statementComment); + } else { + commentAsBytes = StringUtils.getBytes(statementComment, this.charConverter, + this.charEncoding, this.connection + .getServerCharacterEncoding(), this.connection + .parserKnowsUnicode(), getExceptionInterceptor()); + } + + ensurePacketSize += commentAsBytes.length; + ensurePacketSize += 6; // for /*[space] [space]*/ } - } - - if (ensurePacketSize != 0) { - sendPacket.ensureCapacity(ensurePacketSize); - } - - for (int i = 0; i < batchedParameterStrings.length; i++) { - if ((batchedParameterStrings[i] == null) - && (batchedParameterStreams[i] == null)) { - throw SQLError.createSQLException(Messages - .getString("PreparedStatement.40") //$NON-NLS-1$ - + (i + 1), SQLError.SQL_STATE_WRONG_NO_OF_PARAMETERS); + + for (int i = 0; i < batchedParameterStrings.length; i++) { + if (batchedIsStream[i] && useStreamLengths) { + ensurePacketSize += batchedStreamLengths[i]; + } } - - sendPacket.writeBytesNoNull(this.staticSqlStrings[i]); - - if (batchedIsStream[i]) { - streamToBytes(sendPacket, batchedParameterStreams[i], true, - batchedStreamLengths[i], useStreamLengths); - } else { - sendPacket.writeBytesNoNull(batchedParameterStrings[i]); + + if (ensurePacketSize != 0) { + sendPacket.ensureCapacity(ensurePacketSize); } + + if (commentAsBytes != null) { + sendPacket.writeBytesNoNull(Constants.SLASH_STAR_SPACE_AS_BYTES); + sendPacket.writeBytesNoNull(commentAsBytes); + sendPacket.writeBytesNoNull(Constants.SPACE_STAR_SLASH_SPACE_AS_BYTES); + } + + for (int i = 0; i < batchedParameterStrings.length; i++) { + checkAllParametersSet(batchedParameterStrings[i], + batchedParameterStreams[i], i); + + sendPacket.writeBytesNoNull(this.staticSqlStrings[i]); + + if (batchedIsStream[i]) { + streamToBytes(sendPacket, batchedParameterStreams[i], true, + batchedStreamLengths[i], useStreamLengths); + } else { + sendPacket.writeBytesNoNull(batchedParameterStrings[i]); + } + } + + sendPacket + .writeBytesNoNull(this.staticSqlStrings[batchedParameterStrings.length]); + + return sendPacket; } + } - sendPacket - .writeBytesNoNull(this.staticSqlStrings[batchedParameterStrings.length]); + private void checkAllParametersSet(byte[] parameterString, + InputStream parameterStream, int columnIndex) throws SQLException { + if ((parameterString == null) + && parameterStream == null) { - return sendPacket; + throw SQLError.createSQLException(Messages + .getString("PreparedStatement.40") //$NON-NLS-1$ + + (columnIndex + 1), SQLError.SQL_STATE_WRONG_NO_OF_PARAMETERS, getExceptionInterceptor()); + } } - private String generateBatchedInsertSQL(String valuesClause, int numBatches) { - StringBuffer newStatementSql = new StringBuffer(this.originalSql - .length() - + (numBatches * (valuesClause.length() + 1))); - - newStatementSql.append(this.originalSql); - - for (int i = 0; i < numBatches - 1; i++) { - newStatementSql.append(','); - newStatementSql.append(valuesClause); + /** + * Returns a prepared statement for the number of batched parameters, used when re-writing batch INSERTs. + */ + protected PreparedStatement prepareBatchedInsertSQL(MySQLConnection localConn, int numBatches) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + PreparedStatement pstmt = new PreparedStatement(localConn, "Rewritten batch of: " + this.originalSql, this.currentCatalog, this.parseInfo.getParseInfoForBatch(numBatches)); + pstmt.setRetrieveGeneratedKeys(this.retrieveGeneratedKeys); + pstmt.rewrittenBatchSize = numBatches; + + return pstmt; } + } - return newStatementSql.toString(); + protected void setRetrieveGeneratedKeys(boolean flag) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.retrieveGeneratedKeys = flag; + } } + protected int rewrittenBatchSize = 0; + + public int getRewrittenBatchSize() { + return this.rewrittenBatchSize; + } + + public String getNonRewrittenSql() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + int indexOfBatch = this.originalSql.indexOf(" of: "); + + if (indexOfBatch != -1) { + return this.originalSql.substring(indexOfBatch + 5); + } + + return this.originalSql; + } + } + + /** * DOCUMENT ME! * @@ -1783,28 +2541,75 @@ */ public byte[] getBytesRepresentation(int parameterIndex) throws SQLException { - if (this.isStream[parameterIndex]) { - return streamToBytes(this.parameterStreams[parameterIndex], false, - this.streamLengths[parameterIndex], this.connection - .getUseStreamLengthsInPrepStmts()); + synchronized (checkClosed().getConnectionMutex()) { + if (this.isStream[parameterIndex]) { + return streamToBytes(this.parameterStreams[parameterIndex], false, + this.streamLengths[parameterIndex], this.connection + .getUseStreamLengthsInPrepStmts()); + } + + byte[] parameterVal = this.parameterValues[parameterIndex]; + + if (parameterVal == null) { + return null; + } + + if ((parameterVal[0] == '\'') + && (parameterVal[parameterVal.length - 1] == '\'')) { + byte[] valNoQuotes = new byte[parameterVal.length - 2]; + System.arraycopy(parameterVal, 1, valNoQuotes, 0, + parameterVal.length - 2); + + return valNoQuotes; + } + + return parameterVal; } - - byte[] parameterVal = this.parameterValues[parameterIndex]; - - if (parameterVal == null) { - return null; + } + + /** + * Get bytes representation for a parameter in a statement batch. + * @param parameterIndex + * @param commandIndex + * @return + * @throws SQLException + */ + protected byte[] getBytesRepresentationForBatch(int parameterIndex, int commandIndex) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + Object batchedArg = batchedArgs.get(commandIndex); + if (batchedArg instanceof String) { + try { + return (StringUtils.getBytes((String)batchedArg, charEncoding)); + + } catch (UnsupportedEncodingException uue) { + throw new RuntimeException(Messages + .getString("PreparedStatement.32") //$NON-NLS-1$ + + this.charEncoding + + Messages.getString("PreparedStatement.33")); //$NON-NLS-1$ + } + } + + BatchParams params = (BatchParams)batchedArg; + if (params.isStream[parameterIndex]) + return streamToBytes(params.parameterStreams[parameterIndex], false, + params.streamLengths[parameterIndex], + connection.getUseStreamLengthsInPrepStmts()); + byte parameterVal[] = params.parameterStrings[parameterIndex]; + if (parameterVal == null) + return null; + + if ((parameterVal[0] == '\'') + && (parameterVal[parameterVal.length - 1] == '\'')) { + byte[] valNoQuotes = new byte[parameterVal.length - 2]; + System.arraycopy(parameterVal, 1, valNoQuotes, 0, + parameterVal.length - 2); + + return valNoQuotes; + } + + return parameterVal; } - - if ((parameterVal[0] == '\'') - && (parameterVal[parameterVal.length - 1] == '\'')) { - byte[] valNoQuotes = new byte[parameterVal.length - 2]; - System.arraycopy(parameterVal, 1, valNoQuotes, 0, - parameterVal.length - 2); - - return valNoQuotes; - } - - return parameterVal; } // --------------------------JDBC 2.0----------------------------- @@ -1865,20 +2670,20 @@ char c; char separator; StringReader reader = new StringReader(dt + " "); //$NON-NLS-1$ - ArrayList vec = new ArrayList(); - ArrayList vecRemovelist = new ArrayList(); + ArrayList vec = new ArrayList(); + ArrayList vecRemovelist = new ArrayList(); Object[] nv = new Object[3]; Object[] v; - nv[0] = new Character('y'); + nv[0] = Character.valueOf('y'); nv[1] = new StringBuffer(); - nv[2] = new Integer(0); + nv[2] = Integer.valueOf(0); vec.add(nv); if (toTime) { nv = new Object[3]; - nv[0] = new Character('h'); + nv[0] = Character.valueOf('h'); nv[1] = new StringBuffer(); - nv[2] = new Integer(0); + nv[2] = Integer.valueOf(0); vec.add(nv); } @@ -1887,7 +2692,7 @@ maxvecs = vec.size(); for (count = 0; count < maxvecs; count++) { - v = (Object[]) vec.get(count); + v = vec.get(count); n = ((Integer) v[2]).intValue(); c = getSuccessor(((Character) v[0]).charValue(), n); @@ -1898,7 +2703,7 @@ ((StringBuffer) v[1]).append(separator); if ((c == 'X') || (c == 'Y')) { - v[2] = new Integer(4); + v[2] = Integer.valueOf(4); } } } else { @@ -1907,34 +2712,34 @@ nv = new Object[3]; nv[1] = (new StringBuffer(((StringBuffer) v[1]) .toString())).append('M'); - nv[0] = new Character('M'); - nv[2] = new Integer(1); + nv[0] = Character.valueOf('M'); + nv[2] = Integer.valueOf(1); vec.add(nv); } else if (c == 'Y') { c = 'M'; nv = new Object[3]; nv[1] = (new StringBuffer(((StringBuffer) v[1]) .toString())).append('d'); - nv[0] = new Character('d'); - nv[2] = new Integer(1); + nv[0] = Character.valueOf('d'); + nv[2] = Integer.valueOf(1); vec.add(nv); } ((StringBuffer) v[1]).append(c); if (c == ((Character) v[0]).charValue()) { - v[2] = new Integer(n + 1); + v[2] = Integer.valueOf(n + 1); } else { - v[0] = new Character(c); - v[2] = new Integer(1); + v[0] = Character.valueOf(c); + v[2] = Integer.valueOf(1); } } } int size = vecRemovelist.size(); for (int i = 0; i < size; i++) { - v = (Object[]) vecRemovelist.get(i); + v = vecRemovelist.get(i); vec.remove(v); } @@ -1944,7 +2749,7 @@ int size = vec.size(); for (int i = 0; i < size; i++) { - v = (Object[]) vec.get(i); + v = vec.get(i); c = ((Character) v[0]).charValue(); n = ((Integer) v[2]).intValue(); @@ -1966,7 +2771,7 @@ } vecRemovelist.clear(); - v = (Object[]) vec.get(0); // might throw exception + v = vec.get(0); // might throw exception StringBuffer format = (StringBuffer) v[1]; format.setLength(format.length() - 1); @@ -1986,103 +2791,109 @@ public java.sql.ResultSetMetaData getMetaData() throws SQLException { - // - // We could just tack on a LIMIT 0 here no matter what the - // statement, and check if a result set was returned or not, - // but I'm not comfortable with that, myself, so we take - // the "safer" road, and only allow metadata for _actual_ - // SELECTS (but not SHOWs). - // - // CALL's are trapped further up and you end up with a - // CallableStatement anyway. - // - - if (!isSelectQuery()) { - return null; - } - - PreparedStatement mdStmt = null; - java.sql.ResultSet mdRs = null; - - if (this.pstmtResultMetaData == null) { - try { - mdStmt = new PreparedStatement(this.connection, - this.originalSql, this.currentCatalog, this.parseInfo); - - mdStmt.setMaxRows(0); - - int paramCount = this.parameterValues.length; - - for (int i = 1; i <= paramCount; i++) { - mdStmt.setString(i, ""); //$NON-NLS-1$ - } - - boolean hadResults = mdStmt.execute(); - - if (hadResults) { - mdRs = mdStmt.getResultSet(); - - this.pstmtResultMetaData = mdRs.getMetaData(); - } else { - this.pstmtResultMetaData = new ResultSetMetaData( - new Field[0], - this.connection.getUseOldAliasMetadataBehavior()); - } - } finally { - SQLException sqlExRethrow = null; - - if (mdRs != null) { - try { - mdRs.close(); - } catch (SQLException sqlEx) { - sqlExRethrow = sqlEx; + synchronized (checkClosed().getConnectionMutex()) { + // + // We could just tack on a LIMIT 0 here no matter what the + // statement, and check if a result set was returned or not, + // but I'm not comfortable with that, myself, so we take + // the "safer" road, and only allow metadata for _actual_ + // SELECTS (but not SHOWs). + // + // CALL's are trapped further up and you end up with a + // CallableStatement anyway. + // + + if (!isSelectQuery()) { + return null; + } + + PreparedStatement mdStmt = null; + java.sql.ResultSet mdRs = null; + + if (this.pstmtResultMetaData == null) { + try { + mdStmt = new PreparedStatement(this.connection, + this.originalSql, this.currentCatalog, this.parseInfo); + + mdStmt.setMaxRows(1); + + int paramCount = this.parameterValues.length; + + for (int i = 1; i <= paramCount; i++) { + mdStmt.setString(i, ""); //$NON-NLS-1$ } - - mdRs = null; - } - - if (mdStmt != null) { - try { - mdStmt.close(); - } catch (SQLException sqlEx) { - sqlExRethrow = sqlEx; + + boolean hadResults = mdStmt.execute(); + + if (hadResults) { + mdRs = mdStmt.getResultSet(); + + this.pstmtResultMetaData = mdRs.getMetaData(); + } else { + this.pstmtResultMetaData = new ResultSetMetaData(new Field[0], + connection.getUseOldAliasMetadataBehavior(), connection.getYearIsDateType(), + getExceptionInterceptor()); } - - mdStmt = null; + } finally { + SQLException sqlExRethrow = null; + + if (mdRs != null) { + try { + mdRs.close(); + } catch (SQLException sqlEx) { + sqlExRethrow = sqlEx; + } + + mdRs = null; + } + + if (mdStmt != null) { + try { + mdStmt.close(); + } catch (SQLException sqlEx) { + sqlExRethrow = sqlEx; + } + + mdStmt = null; + } + + if (sqlExRethrow != null) { + throw sqlExRethrow; + } } - - if (sqlExRethrow != null) { - throw sqlExRethrow; - } } + + return this.pstmtResultMetaData; } - - return this.pstmtResultMetaData; } - protected boolean isSelectQuery() { - return StringUtils.startsWithIgnoreCaseAndWs( - StringUtils.stripComments(this.originalSql, - "'\"", "'\"", true, false, true, true), - "SELECT"); + protected boolean isSelectQuery() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return StringUtils.startsWithIgnoreCaseAndWs( + StringUtils.stripComments(this.originalSql, + "'\"", "'\"", true, false, true, true), + "SELECT"); + } } /** * @see PreparedStatement#getParameterMetaData() */ public ParameterMetaData getParameterMetaData() throws SQLException { - if (this.parameterMetaData == null) { - if (this.connection.getGenerateSimpleParameterMetadata()) { - this.parameterMetaData = new MysqlParameterMetadata(this.parameterCount); - } else { - this.parameterMetaData = new MysqlParameterMetadata( - null, this.parameterCount); + synchronized (checkClosed().getConnectionMutex()) { + if (this.parameterMetaData == null) { + if (this.connection.getGenerateSimpleParameterMetadata()) { + this.parameterMetaData = new MysqlParameterMetadata(this.parameterCount); + } else { + this.parameterMetaData = new MysqlParameterMetadata( + null, this.parameterCount, getExceptionInterceptor()); + } } + + return this.parameterMetaData; } - - return this.parameterMetaData; - } +} ParseInfo getParseInfo() { return this.parseInfo; @@ -2126,38 +2937,43 @@ } private void initializeFromParseInfo() throws SQLException { - this.staticSqlStrings = this.parseInfo.staticSql; - this.hasLimitClause = this.parseInfo.foundLimitClause; - this.isLoadDataQuery = this.parseInfo.foundLoadData; - this.firstCharOfStmt = this.parseInfo.firstStmtChar; - - this.parameterCount = this.staticSqlStrings.length - 1; - - this.parameterValues = new byte[this.parameterCount][]; - this.parameterStreams = new InputStream[this.parameterCount]; - this.isStream = new boolean[this.parameterCount]; - this.streamLengths = new int[this.parameterCount]; - this.isNull = new boolean[this.parameterCount]; - - clearParameters(); - - for (int j = 0; j < this.parameterCount; j++) { - this.isStream[j] = false; - } + synchronized (checkClosed().getConnectionMutex()) { + this.staticSqlStrings = this.parseInfo.staticSql; + this.isLoadDataQuery = this.parseInfo.foundLoadData; + this.firstCharOfStmt = this.parseInfo.firstStmtChar; + + this.parameterCount = this.staticSqlStrings.length - 1; + + this.parameterValues = new byte[this.parameterCount][]; + this.parameterStreams = new InputStream[this.parameterCount]; + this.isStream = new boolean[this.parameterCount]; + this.streamLengths = new int[this.parameterCount]; + this.isNull = new boolean[this.parameterCount]; + this.parameterTypes = new int[this.parameterCount]; - this.statementAfterCommentsPos = this.parseInfo.statementStartPos; + clearParameters(); + + for (int j = 0; j < this.parameterCount; j++) { + this.isStream[j] = false; + } + } } - boolean isNull(int paramIndex) { - return this.isNull[paramIndex]; + boolean isNull(int paramIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.isNull[paramIndex]; + } } private final int readblock(InputStream i, byte[] b) throws SQLException { try { return i.read(b); - } catch (Throwable E) { - throw SQLError.createSQLException(Messages.getString("PreparedStatement.56") //$NON-NLS-1$ - + E.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR); + } catch (Throwable ex) { + SQLException sqlEx = SQLError.createSQLException(Messages.getString("PreparedStatement.56") //$NON-NLS-1$ + + ex.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; } } @@ -2171,9 +2987,12 @@ } return i.read(b, 0, lengthToRead); - } catch (Throwable E) { - throw SQLError.createSQLException(Messages.getString("PreparedStatement.55") //$NON-NLS-1$ - + E.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR); + } catch (Throwable ex) { + SQLException sqlEx = SQLError.createSQLException(Messages.getString("PreparedStatement.56") //$NON-NLS-1$ + + ex.getClass().getName(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; } } @@ -2188,30 +3007,42 @@ */ protected void realClose(boolean calledExplicitly, boolean closeOpenResults) throws SQLException { - if (this.useUsageAdvisor) { - if (this.numberOfExecutions <= 1) { - String message = Messages.getString("PreparedStatement.43"); //$NON-NLS-1$ + MySQLConnection locallyScopedConn = this.connection; - this.eventSink.consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_WARN, "", this.currentCatalog, //$NON-NLS-1$ - this.connectionId, this.getId(), -1, System - .currentTimeMillis(), 0, Constants.MILLIS_I18N, - null, - this.pointOfOrigin, message)); + if (locallyScopedConn == null) return; // already closed + + synchronized (locallyScopedConn.getConnectionMutex()) { + + // additional check in case Statement was closed + // while current thread was waiting for lock + if (this.isClosed) return; + + if (this.useUsageAdvisor) { + if (this.numberOfExecutions <= 1) { + String message = Messages.getString("PreparedStatement.43"); //$NON-NLS-1$ + + this.eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, "", this.currentCatalog, //$NON-NLS-1$ + this.connectionId, this.getId(), -1, System + .currentTimeMillis(), 0, Constants.MILLIS_I18N, + null, + this.pointOfOrigin, message)); + } } + + super.realClose(calledExplicitly, closeOpenResults); + + this.dbmd = null; + this.originalSql = null; + this.staticSqlStrings = null; + this.parameterValues = null; + this.parameterStreams = null; + this.isStream = null; + this.streamLengths = null; + this.isNull = null; + this.streamConvertBuf = null; + this.parameterTypes = null; } - - super.realClose(calledExplicitly, closeOpenResults); - - this.dbmd = null; - this.originalSql = null; - this.staticSqlStrings = null; - this.parameterValues = null; - this.parameterStreams = null; - this.isStream = null; - this.streamLengths = null; - this.isNull = null; - this.streamConvertBuf = null; } /** @@ -2228,7 +3059,7 @@ * DOCUMENT ME! */ public void setArray(int i, Array x) throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** @@ -2281,6 +3112,8 @@ } else { setInternal(parameterIndex, StringUtils .fixDecimalExponent(StringUtils.consistentToString(x))); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.DECIMAL; } } @@ -2306,31 +3139,39 @@ */ public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - int parameterIndexOffset = getParameterIndexOffset(); - - if ((parameterIndex < 1) - || (parameterIndex > this.staticSqlStrings.length)) { - throw SQLError.createSQLException( - Messages.getString("PreparedStatement.2") //$NON-NLS-1$ - + parameterIndex - + Messages.getString("PreparedStatement.3") + this.staticSqlStrings.length + Messages.getString("PreparedStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } else if (parameterIndexOffset == -1 && parameterIndex == 1) { - throw SQLError.createSQLException("Can't set IN parameter for return value of stored function call.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.BINARY); + } else { + int parameterIndexOffset = getParameterIndexOffset(); + + if ((parameterIndex < 1) + || (parameterIndex > this.staticSqlStrings.length)) { + throw SQLError.createSQLException( + Messages.getString("PreparedStatement.2") //$NON-NLS-1$ + + parameterIndex + + Messages.getString("PreparedStatement.3") + this.staticSqlStrings.length + Messages.getString("PreparedStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } else if (parameterIndexOffset == -1 && parameterIndex == 1) { + throw SQLError.createSQLException("Can't set IN parameter for return value of stored function call.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + + this.parameterStreams[parameterIndex - 1 + parameterIndexOffset] = x; + this.isStream[parameterIndex - 1 + parameterIndexOffset] = true; + this.streamLengths[parameterIndex - 1 + parameterIndexOffset] = length; + this.isNull[parameterIndex - 1 + parameterIndexOffset] = false; + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.BLOB; } - - - this.parameterStreams[parameterIndex - 1 + parameterIndexOffset] = x; - this.isStream[parameterIndex - 1 + parameterIndexOffset] = true; - this.streamLengths[parameterIndex - 1 + parameterIndexOffset] = length; - this.isNull[parameterIndex - 1 + parameterIndexOffset] = false; } } + public void setBlob(int parameterIndex, InputStream inputStream, long length) + throws SQLException { + setBinaryStream(parameterIndex, inputStream, (int)length); + } + /** * JDBC 2.0 Set a BLOB parameter. * @@ -2354,6 +3195,8 @@ bytesOut.write('\''); setInternal(i, bytesOut.toByteArray()); + + this.parameterTypes[i - 1 + getParameterIndexOffset()] = Types.BLOB; } } @@ -2374,6 +3217,8 @@ setInternal(parameterIndex, x ? "1" : "0"); //$NON-NLS-1$ //$NON-NLS-2$ } else { setInternal(parameterIndex, x ? "'t'" : "'f'"); //$NON-NLS-1$ //$NON-NLS-2$ + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.BOOLEAN; } } @@ -2391,6 +3236,8 @@ */ public void setByte(int parameterIndex, byte x) throws SQLException { setInternal(parameterIndex, String.valueOf(x)); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.TINYINT; } /** @@ -2408,124 +3255,138 @@ */ public void setBytes(int parameterIndex, byte[] x) throws SQLException { setBytes(parameterIndex, x, true, true); + + if (x != null) { + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.BINARY; + } } protected void setBytes(int parameterIndex, byte[] x, boolean checkForIntroducer, boolean escapeForMBChars) throws SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - String connectionEncoding = this.connection.getEncoding(); - - if (this.connection.isNoBackslashEscapesSet() - || (escapeForMBChars - && this.connection.getUseUnicode() - && connectionEncoding != null - && CharsetMapping.isMultibyteCharset(connectionEncoding))) { - - // Send as hex - - ByteArrayOutputStream bOut = new ByteArrayOutputStream( - (x.length * 2) + 3); - bOut.write('x'); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.BINARY); + } else { + String connectionEncoding = this.connection.getEncoding(); + + try { + if (this.connection.isNoBackslashEscapesSet() + || (escapeForMBChars + && this.connection.getUseUnicode() + && connectionEncoding != null + && CharsetMapping.isMultibyteCharset(connectionEncoding))) { + + // Send as hex + + ByteArrayOutputStream bOut = new ByteArrayOutputStream( + (x.length * 2) + 3); + bOut.write('x'); + bOut.write('\''); + + for (int i = 0; i < x.length; i++) { + int lowBits = (x[i] & 0xff) / 16; + int highBits = (x[i] & 0xff) % 16; + + bOut.write(HEX_DIGITS[lowBits]); + bOut.write(HEX_DIGITS[highBits]); + } + + bOut.write('\''); + + setInternal(parameterIndex, bOut.toByteArray()); + + return; + } + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + // escape them + int numBytes = x.length; + + int pad = 2; + + boolean needsIntroducer = checkForIntroducer + && this.connection.versionMeetsMinimum(4, 1, 0); + + if (needsIntroducer) { + pad += 7; + } + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(numBytes + + pad); + + if (needsIntroducer) { + bOut.write('_'); + bOut.write('b'); + bOut.write('i'); + bOut.write('n'); + bOut.write('a'); + bOut.write('r'); + bOut.write('y'); + } bOut.write('\''); - - for (int i = 0; i < x.length; i++) { - int lowBits = (x[i] & 0xff) / 16; - int highBits = (x[i] & 0xff) % 16; - - bOut.write(HEX_DIGITS[lowBits]); - bOut.write(HEX_DIGITS[highBits]); + + for (int i = 0; i < numBytes; ++i) { + byte b = x[i]; + + switch (b) { + case 0: /* Must be escaped for 'mysql' */ + bOut.write('\\'); + bOut.write('0'); + + break; + + case '\n': /* Must be escaped for logs */ + bOut.write('\\'); + bOut.write('n'); + + break; + + case '\r': + bOut.write('\\'); + bOut.write('r'); + + break; + + case '\\': + bOut.write('\\'); + bOut.write('\\'); + + break; + + case '\'': + bOut.write('\\'); + bOut.write('\''); + + break; + + case '"': /* Better safe than sorry */ + bOut.write('\\'); + bOut.write('"'); + + break; + + case '\032': /* This gives problems on Win32 */ + bOut.write('\\'); + bOut.write('Z'); + + break; + + default: + bOut.write(b); + } } - + bOut.write('\''); - + setInternal(parameterIndex, bOut.toByteArray()); - - return; } - - // escape them - int numBytes = x.length; - - int pad = 2; - - boolean needsIntroducer = checkForIntroducer - && this.connection.versionMeetsMinimum(4, 1, 0); - - if (needsIntroducer) { - pad += 7; - } - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(numBytes - + pad); - - if (needsIntroducer) { - bOut.write('_'); - bOut.write('b'); - bOut.write('i'); - bOut.write('n'); - bOut.write('a'); - bOut.write('r'); - bOut.write('y'); - } - bOut.write('\''); - - for (int i = 0; i < numBytes; ++i) { - byte b = x[i]; - - switch (b) { - case 0: /* Must be escaped for 'mysql' */ - bOut.write('\\'); - bOut.write('0'); - - break; - - case '\n': /* Must be escaped for logs */ - bOut.write('\\'); - bOut.write('n'); - - break; - - case '\r': - bOut.write('\\'); - bOut.write('r'); - - break; - - case '\\': - bOut.write('\\'); - bOut.write('\\'); - - break; - - case '\'': - bOut.write('\\'); - bOut.write('\''); - - break; - - case '"': /* Better safe than sorry */ - bOut.write('\\'); - bOut.write('"'); - - break; - - case '\032': /* This gives problems on Win32 */ - bOut.write('\\'); - bOut.write('Z'); - - break; - - default: - bOut.write(b); - } - } - - bOut.write('\''); - - setInternal(parameterIndex, bOut.toByteArray()); } } @@ -2581,63 +3442,67 @@ */ public void setCharacterStream(int parameterIndex, java.io.Reader reader, int length) throws SQLException { - try { - if (reader == null) { - setNull(parameterIndex, Types.LONGVARCHAR); - } else { - char[] c = null; - int len = 0; - - boolean useLength = this.connection - .getUseStreamLengthsInPrepStmts(); - - String forcedEncoding = this.connection.getClobCharacterEncoding(); - - if (useLength && (length != -1)) { - c = new char[length]; - - int numCharsRead = readFully(reader, c, length); // blocks - // until - // all - // read - - if (forcedEncoding == null) { - setString(parameterIndex, new String(c, 0, numCharsRead)); - } else { - try { - setBytes(parameterIndex, new String(c, - 0, - numCharsRead).getBytes(forcedEncoding)); - } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException("Unsupported character encoding " + - forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - } + synchronized (checkClosed().getConnectionMutex()) { + try { + if (reader == null) { + setNull(parameterIndex, Types.LONGVARCHAR); } else { - c = new char[4096]; - - StringBuffer buf = new StringBuffer(); - - while ((len = reader.read(c)) != -1) { - buf.append(c, 0, len); - } - - if (forcedEncoding == null) { - setString(parameterIndex, buf.toString()); + char[] c = null; + int len = 0; + + boolean useLength = this.connection + .getUseStreamLengthsInPrepStmts(); + + String forcedEncoding = this.connection.getClobCharacterEncoding(); + + if (useLength && (length != -1)) { + c = new char[length]; + + int numCharsRead = readFully(reader, c, length); // blocks + // until + // all + // read + + if (forcedEncoding == null) { + setString(parameterIndex, new String(c, 0, numCharsRead)); + } else { + try { + setBytes(parameterIndex, StringUtils.getBytes(new String(c, + 0, + numCharsRead), forcedEncoding)); + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException("Unsupported character encoding " + + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } } else { - try { - setBytes(parameterIndex, - buf.toString().getBytes(forcedEncoding)); - } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException("Unsupported character encoding " + - forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + c = new char[4096]; + + StringBuffer buf = new StringBuffer(); + + while ((len = reader.read(c)) != -1) { + buf.append(c, 0, len); } + + if (forcedEncoding == null) { + setString(parameterIndex, buf.toString()); + } else { + try { + setBytes(parameterIndex, + StringUtils.getBytes(buf.toString(), forcedEncoding)); + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException("Unsupported character encoding " + + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } } + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.CLOB; } + } catch (java.io.IOException ioEx) { + throw SQLError.createSQLException(ioEx.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - } catch (java.io.IOException ioEx) { - throw SQLError.createSQLException(ioEx.toString(), - SQLError.SQL_STATE_GENERAL_ERROR); } } @@ -2653,23 +3518,26 @@ * if a database error occurs */ public void setClob(int i, Clob x) throws SQLException { - if (x == null) { - setNull(i, Types.CLOB); - - return; - } - - String forcedEncoding = this.connection.getClobCharacterEncoding(); - - if (forcedEncoding == null) { - setString(i, x.getSubString(1L, (int) x.length())); - } else { - try { - setBytes(i, x.getSubString(1L, - (int)x.length()).getBytes(forcedEncoding)); - } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException("Unsupported character encoding " + - forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(i, Types.CLOB); + } else { + + String forcedEncoding = this.connection.getClobCharacterEncoding(); + + if (forcedEncoding == null) { + setString(i, x.getSubString(1L, (int) x.length())); + } else { + try { + setBytes(i, StringUtils.getBytes(x.getSubString(1L, + (int)x.length()), forcedEncoding)); + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException("Unsupported character encoding " + + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + this.parameterTypes[i - 1 + getParameterIndexOffset()] = Types.CLOB; } } } @@ -2688,15 +3556,7 @@ */ public void setDate(int parameterIndex, java.sql.Date x) throws java.sql.SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.DATE); - } else { - // FIXME: Have instance version of this, problem as it's - // not thread-safe :( - SimpleDateFormat dateFormatter = new SimpleDateFormat( - "''yyyy-MM-dd''", Locale.US); //$NON-NLS-1$ - setInternal(parameterIndex, dateFormatter.format(x)); - } + setDate(parameterIndex, x, null); } /** @@ -2715,7 +3575,23 @@ */ public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) throws SQLException { - setDate(parameterIndex, x); + if (x == null) { + setNull(parameterIndex, java.sql.Types.DATE); + } else { + checkClosed(); + + if (!this.useLegacyDatetimeCode) { + newSetDateInternal(parameterIndex, x, cal); + } else { + // FIXME: Have instance version of this, problem as it's + // not thread-safe :( + SimpleDateFormat dateFormatter = new SimpleDateFormat( + "''yyyy-MM-dd''", Locale.US); //$NON-NLS-1$ + setInternal(parameterIndex, dateFormatter.format(x)); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.DATE; + } + } } /** @@ -2731,18 +3607,21 @@ * if a database access error occurs */ public void setDouble(int parameterIndex, double x) throws SQLException { - - if (!this.connection.getAllowNanAndInf() - && (x == Double.POSITIVE_INFINITY - || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) { - throw SQLError.createSQLException("'" + x - + "' is not a valid numeric or approximate numeric value", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - + synchronized (checkClosed().getConnectionMutex()) { + if (!this.connection.getAllowNanAndInf() + && (x == Double.POSITIVE_INFINITY + || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) { + throw SQLError.createSQLException("'" + x + + "' is not a valid numeric or approximate numeric value", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + + } + + setInternal(parameterIndex, StringUtils.fixDecimalExponent(String + .valueOf(x))); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.DOUBLE; } - - setInternal(parameterIndex, StringUtils.fixDecimalExponent(String - .valueOf(x))); } /** @@ -2760,6 +3639,8 @@ public void setFloat(int parameterIndex, float x) throws SQLException { setInternal(parameterIndex, StringUtils.fixDecimalExponent(String .valueOf(x))); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.FLOAT; } /** @@ -2776,55 +3657,63 @@ */ public void setInt(int parameterIndex, int x) throws SQLException { setInternal(parameterIndex, String.valueOf(x)); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.INTEGER; } - private final void setInternal(int paramIndex, byte[] val) + protected final void setInternal(int paramIndex, byte[] val) throws SQLException { - if (this.isClosed) { - throw SQLError.createSQLException(Messages.getString("PreparedStatement.48"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + synchronized (checkClosed().getConnectionMutex()) { + + int parameterIndexOffset = getParameterIndexOffset(); + + checkBounds(paramIndex, parameterIndexOffset); + + this.isStream[paramIndex - 1 + parameterIndexOffset] = false; + this.isNull[paramIndex - 1 + parameterIndexOffset] = false; + this.parameterStreams[paramIndex - 1 + parameterIndexOffset] = null; + this.parameterValues[paramIndex - 1 + parameterIndexOffset] = val; } - - int parameterIndexOffset = getParameterIndexOffset(); - - if ((paramIndex < 1)) { - throw SQLError.createSQLException( - Messages.getString("PreparedStatement.49") //$NON-NLS-1$ - + paramIndex - + Messages.getString("PreparedStatement.50"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } else if (paramIndex > this.parameterCount) { - throw SQLError.createSQLException( - Messages.getString("PreparedStatement.51") //$NON-NLS-1$ - + paramIndex - + Messages.getString("PreparedStatement.52") + (this.parameterValues.length) + Messages.getString("PreparedStatement.53"), //$NON-NLS-1$ //$NON-NLS-2$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } else if (parameterIndexOffset == -1 && paramIndex == 1) { - throw SQLError.createSQLException("Can't set IN parameter for return value of stored function call.", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } + } - this.isStream[paramIndex - 1 + parameterIndexOffset] = false; - this.isNull[paramIndex - 1 + parameterIndexOffset] = false; - this.parameterStreams[paramIndex - 1 + parameterIndexOffset] = null; - this.parameterValues[paramIndex - 1 + parameterIndexOffset] = val; + protected void checkBounds(int paramIndex, int parameterIndexOffset) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if ((paramIndex < 1)) { + throw SQLError.createSQLException( + Messages.getString("PreparedStatement.49") //$NON-NLS-1$ + + paramIndex + + Messages.getString("PreparedStatement.50"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } else if (paramIndex > this.parameterCount) { + throw SQLError.createSQLException( + Messages.getString("PreparedStatement.51") //$NON-NLS-1$ + + paramIndex + + Messages.getString("PreparedStatement.52") + (this.parameterValues.length) + Messages.getString("PreparedStatement.53"), //$NON-NLS-1$ //$NON-NLS-2$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } else if (parameterIndexOffset == -1 && paramIndex == 1) { + throw SQLError.createSQLException("Can't set IN parameter for return value of stored function call.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } } - private final void setInternal(int paramIndex, String val) + protected final void setInternal(int paramIndex, String val) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - byte[] parameterAsBytes = null; - - if (this.charConverter != null) { - parameterAsBytes = this.charConverter.toBytes(val); - } else { - parameterAsBytes = StringUtils.getBytes(val, this.charConverter, - this.charEncoding, this.connection - .getServerCharacterEncoding(), this.connection - .parserKnowsUnicode()); + byte[] parameterAsBytes = null; + + if (this.charConverter != null) { + parameterAsBytes = this.charConverter.toBytes(val); + } else { + parameterAsBytes = StringUtils.getBytes(val, this.charConverter, + this.charEncoding, this.connection + .getServerCharacterEncoding(), this.connection + .parserKnowsUnicode(), getExceptionInterceptor()); + } + + setInternal(paramIndex, parameterAsBytes); } - - setInternal(paramIndex, parameterAsBytes); } /** @@ -2841,6 +3730,8 @@ */ public void setLong(int parameterIndex, long x) throws SQLException { setInternal(parameterIndex, String.valueOf(x)); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.BIGINT; } /** @@ -2860,8 +3751,12 @@ * if a database access error occurs */ public void setNull(int parameterIndex, int sqlType) throws SQLException { - setInternal(parameterIndex, "null"); //$NON-NLS-1$ - this.isNull[parameterIndex - 1] = true; + synchronized (checkClosed().getConnectionMutex()) { + setInternal(parameterIndex, "null"); //$NON-NLS-1$ + this.isNull[parameterIndex - 1 + getParameterIndexOffset()] = true; + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.NULL; + } } /** @@ -2884,24 +3779,31 @@ public void setNull(int parameterIndex, int sqlType, String arg) throws SQLException { setNull(parameterIndex, sqlType); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.NULL; } private void setNumericObject(int parameterIndex, Object parameterObj, int targetSqlType, int scale) throws SQLException { Number parameterAsNum; if (parameterObj instanceof Boolean) { parameterAsNum = ((Boolean) parameterObj) - .booleanValue() ? new Integer(1) : new Integer( + .booleanValue() ? Integer.valueOf(1) : Integer.valueOf( 0); } else if (parameterObj instanceof String) { switch (targetSqlType) { case Types.BIT: - boolean parameterAsBoolean = "true" - .equalsIgnoreCase((String) parameterObj); + if ("1".equals(parameterObj) + || "0".equals(parameterObj)) { + parameterAsNum = Integer.valueOf((String) parameterObj); + } else { + boolean parameterAsBoolean = "true" + .equalsIgnoreCase((String) parameterObj); - parameterAsNum = parameterAsBoolean ? new Integer(1) - : new Integer(0); - + parameterAsNum = parameterAsBoolean ? Integer.valueOf(1) + : Integer.valueOf(0); + } + break; case Types.TINYINT: @@ -2986,7 +3888,7 @@ + scale + "' for DECIMAL argument '" + parameterAsNum + "'", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @@ -3007,63 +3909,54 @@ } } - /** - * DOCUMENT ME! - * - * @param parameterIndex - * DOCUMENT ME! - * @param parameterObj - * DOCUMENT ME! - * - * @throws SQLException - * DOCUMENT ME! - */ public void setObject(int parameterIndex, Object parameterObj) throws SQLException { - if (parameterObj == null) { - setNull(parameterIndex, java.sql.Types.OTHER); - } else { - if (parameterObj instanceof Byte) { - setInt(parameterIndex, ((Byte) parameterObj).intValue()); - } else if (parameterObj instanceof String) { - setString(parameterIndex, (String) parameterObj); - } else if (parameterObj instanceof BigDecimal) { - setBigDecimal(parameterIndex, (BigDecimal) parameterObj); - } else if (parameterObj instanceof Short) { - setShort(parameterIndex, ((Short) parameterObj).shortValue()); - } else if (parameterObj instanceof Integer) { - setInt(parameterIndex, ((Integer) parameterObj).intValue()); - } else if (parameterObj instanceof Long) { - setLong(parameterIndex, ((Long) parameterObj).longValue()); - } else if (parameterObj instanceof Float) { - setFloat(parameterIndex, ((Float) parameterObj).floatValue()); - } else if (parameterObj instanceof Double) { - setDouble(parameterIndex, ((Double) parameterObj).doubleValue()); - } else if (parameterObj instanceof byte[]) { - setBytes(parameterIndex, (byte[]) parameterObj); - } else if (parameterObj instanceof java.sql.Date) { - setDate(parameterIndex, (java.sql.Date) parameterObj); - } else if (parameterObj instanceof Time) { - setTime(parameterIndex, (Time) parameterObj); - } else if (parameterObj instanceof Timestamp) { - setTimestamp(parameterIndex, (Timestamp) parameterObj); - } else if (parameterObj instanceof Boolean) { - setBoolean(parameterIndex, ((Boolean) parameterObj) - .booleanValue()); - } else if (parameterObj instanceof InputStream) { - setBinaryStream(parameterIndex, (InputStream) parameterObj, -1); - } else if (parameterObj instanceof java.sql.Blob) { - setBlob(parameterIndex, (java.sql.Blob) parameterObj); - } else if (parameterObj instanceof java.sql.Clob) { - setClob(parameterIndex, (java.sql.Clob) parameterObj); - } else if (this.connection.getTreatUtilDateAsTimestamp() && - parameterObj instanceof java.util.Date) { - setTimestamp(parameterIndex, new Timestamp( - ((java.util.Date) parameterObj).getTime())); - } else if (parameterObj instanceof BigInteger) { - setString(parameterIndex, parameterObj.toString()); + synchronized (checkClosed().getConnectionMutex()) { + if (parameterObj == null) { + setNull(parameterIndex, java.sql.Types.OTHER); } else { - setSerializableObject(parameterIndex, parameterObj); + if (parameterObj instanceof Byte) { + setInt(parameterIndex, ((Byte) parameterObj).intValue()); + } else if (parameterObj instanceof String) { + setString(parameterIndex, (String) parameterObj); + } else if (parameterObj instanceof BigDecimal) { + setBigDecimal(parameterIndex, (BigDecimal) parameterObj); + } else if (parameterObj instanceof Short) { + setShort(parameterIndex, ((Short) parameterObj).shortValue()); + } else if (parameterObj instanceof Integer) { + setInt(parameterIndex, ((Integer) parameterObj).intValue()); + } else if (parameterObj instanceof Long) { + setLong(parameterIndex, ((Long) parameterObj).longValue()); + } else if (parameterObj instanceof Float) { + setFloat(parameterIndex, ((Float) parameterObj).floatValue()); + } else if (parameterObj instanceof Double) { + setDouble(parameterIndex, ((Double) parameterObj).doubleValue()); + } else if (parameterObj instanceof byte[]) { + setBytes(parameterIndex, (byte[]) parameterObj); + } else if (parameterObj instanceof java.sql.Date) { + setDate(parameterIndex, (java.sql.Date) parameterObj); + } else if (parameterObj instanceof Time) { + setTime(parameterIndex, (Time) parameterObj); + } else if (parameterObj instanceof Timestamp) { + setTimestamp(parameterIndex, (Timestamp) parameterObj); + } else if (parameterObj instanceof Boolean) { + setBoolean(parameterIndex, ((Boolean) parameterObj) + .booleanValue()); + } else if (parameterObj instanceof InputStream) { + setBinaryStream(parameterIndex, (InputStream) parameterObj, -1); + } else if (parameterObj instanceof java.sql.Blob) { + setBlob(parameterIndex, (java.sql.Blob) parameterObj); + } else if (parameterObj instanceof java.sql.Clob) { + setClob(parameterIndex, (java.sql.Clob) parameterObj); + } else if (this.connection.getTreatUtilDateAsTimestamp() && + parameterObj instanceof java.util.Date) { + setTimestamp(parameterIndex, new Timestamp( + ((java.util.Date) parameterObj).getTime())); + } else if (parameterObj instanceof BigInteger) { + setString(parameterIndex, parameterObj.toString()); + } else { + setSerializableObject(parameterIndex, parameterObj); + } } } } @@ -3123,191 +4016,197 @@ */ public void setObject(int parameterIndex, Object parameterObj, int targetSqlType, int scale) throws SQLException { - if (parameterObj == null) { - setNull(parameterIndex, java.sql.Types.OTHER); - } else { - try { - switch (targetSqlType) { - case Types.BOOLEAN: - /* - From Table-B5 in the JDBC-3.0 Spec - - T S I B R F D D N B B C V L - I M N I E L O E U I O H A O - N A T G A O U C M T O A R N - Y L E I L A B I E L R C G - I L G N T L M R E H V - N I E T E A I A A A - T N R L C N R R - T C - H - A - R - ----------------------------------- - Boolean x x x x x x x x x x x x x x - */ + synchronized (checkClosed().getConnectionMutex()) { + if (parameterObj == null) { + setNull(parameterIndex, java.sql.Types.OTHER); + } else { + try { + switch (targetSqlType) { + case Types.BOOLEAN: + /* + From Table-B5 in the JDBC-3.0 Spec - if (parameterObj instanceof Boolean) { - setBoolean(parameterIndex, ((Boolean)parameterObj).booleanValue()); + T S I B R F D D N B B C V L + I M N I E L O E U I O H A O + N A T G A O U C M T O A R N + Y L E I L A B I E L R C G + I L G N T L M R E H V + N I E T E A I A A A + T N R L C N R R + T C + H + A + R + ----------------------------------- + Boolean x x x x x x x x x x x x x x + */ - break; - } else if (parameterObj instanceof String) { - setBoolean(parameterIndex, "true".equalsIgnoreCase((String)parameterObj) || - !"0".equalsIgnoreCase((String)parameterObj)); + if (parameterObj instanceof Boolean) { + setBoolean(parameterIndex, ((Boolean)parameterObj).booleanValue()); + + break; + } else if (parameterObj instanceof String) { + setBoolean(parameterIndex, "true".equalsIgnoreCase((String)parameterObj) || + !"0".equalsIgnoreCase((String)parameterObj)); + + break; + } else if (parameterObj instanceof Number) { + int intValue = ((Number)parameterObj).intValue(); + + setBoolean(parameterIndex, intValue != 0); + + break; + } else { + throw SQLError.createSQLException("No conversion from " + parameterObj.getClass().getName() + + " to Types.BOOLEAN possible.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } - break; - } else if (parameterObj instanceof Number) { - int intValue = ((Number)parameterObj).intValue(); - setBoolean(parameterIndex, intValue != 0); - + case Types.BIT: + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.REAL: + case Types.FLOAT: + case Types.DOUBLE: + case Types.DECIMAL: + case Types.NUMERIC: + + setNumericObject(parameterIndex, parameterObj, targetSqlType, scale); + break; - } else { - throw SQLError.createSQLException("No conversion from " + parameterObj.getClass().getName() + - " to Types.BOOLEAN possible.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - - case Types.BIT: - case Types.TINYINT: - case Types.SMALLINT: - case Types.INTEGER: - case Types.BIGINT: - case Types.REAL: - case Types.FLOAT: - case Types.DOUBLE: - case Types.DECIMAL: - case Types.NUMERIC: - - setNumericObject(parameterIndex, parameterObj, targetSqlType, scale); - - break; - - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - if (parameterObj instanceof BigDecimal) { - setString( - parameterIndex, - (StringUtils - .fixDecimalExponent(StringUtils - .consistentToString((BigDecimal) parameterObj)))); - } else { - setString(parameterIndex, parameterObj.toString()); - } - - break; - - case Types.CLOB: - - if (parameterObj instanceof java.sql.Clob) { - setClob(parameterIndex, (java.sql.Clob) parameterObj); - } else { - setString(parameterIndex, parameterObj.toString()); - } - - break; - - case Types.BINARY: - case Types.VARBINARY: - case Types.LONGVARBINARY: - case Types.BLOB: - - if (parameterObj instanceof byte[]) { - setBytes(parameterIndex, (byte[]) parameterObj); - } else if (parameterObj instanceof java.sql.Blob) { - setBlob(parameterIndex, (java.sql.Blob) parameterObj); - } else { - setBytes(parameterIndex, StringUtils.getBytes( - parameterObj.toString(), this.charConverter, - this.charEncoding, this.connection - .getServerCharacterEncoding(), - this.connection.parserKnowsUnicode())); - } - - break; - - case Types.DATE: - case Types.TIMESTAMP: - - java.util.Date parameterAsDate; - - if (parameterObj instanceof String) { - ParsePosition pp = new ParsePosition(0); - java.text.DateFormat sdf = new java.text.SimpleDateFormat( - getDateTimePattern((String) parameterObj, false), Locale.US); - parameterAsDate = sdf.parse((String) parameterObj, pp); - } else { - parameterAsDate = (java.util.Date) parameterObj; - } - - switch (targetSqlType) { - case Types.DATE: - - if (parameterAsDate instanceof java.sql.Date) { - setDate(parameterIndex, - (java.sql.Date) parameterAsDate); + + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + if (parameterObj instanceof BigDecimal) { + setString( + parameterIndex, + (StringUtils + .fixDecimalExponent(StringUtils + .consistentToString((BigDecimal) parameterObj)))); } else { - setDate(parameterIndex, new java.sql.Date( - parameterAsDate.getTime())); + setString(parameterIndex, parameterObj.toString()); } - + break; - + + case Types.CLOB: + + if (parameterObj instanceof java.sql.Clob) { + setClob(parameterIndex, (java.sql.Clob) parameterObj); + } else { + setString(parameterIndex, parameterObj.toString()); + } + + break; + + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + case Types.BLOB: + + if (parameterObj instanceof byte[]) { + setBytes(parameterIndex, (byte[]) parameterObj); + } else if (parameterObj instanceof java.sql.Blob) { + setBlob(parameterIndex, (java.sql.Blob) parameterObj); + } else { + setBytes(parameterIndex, StringUtils.getBytes( + parameterObj.toString(), this.charConverter, + this.charEncoding, this.connection + .getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor())); + } + + break; + + case Types.DATE: case Types.TIMESTAMP: - - if (parameterAsDate instanceof java.sql.Timestamp) { - setTimestamp(parameterIndex, - (java.sql.Timestamp) parameterAsDate); + + java.util.Date parameterAsDate; + + if (parameterObj instanceof String) { + ParsePosition pp = new ParsePosition(0); + java.text.DateFormat sdf = new java.text.SimpleDateFormat( + getDateTimePattern((String) parameterObj, false), Locale.US); + parameterAsDate = sdf.parse((String) parameterObj, pp); } else { - setTimestamp(parameterIndex, - new java.sql.Timestamp(parameterAsDate - .getTime())); + parameterAsDate = (java.util.Date) parameterObj; } - + + switch (targetSqlType) { + case Types.DATE: + + if (parameterAsDate instanceof java.sql.Date) { + setDate(parameterIndex, + (java.sql.Date) parameterAsDate); + } else { + setDate(parameterIndex, new java.sql.Date( + parameterAsDate.getTime())); + } + + break; + + case Types.TIMESTAMP: + + if (parameterAsDate instanceof java.sql.Timestamp) { + setTimestamp(parameterIndex, + (java.sql.Timestamp) parameterAsDate); + } else { + setTimestamp(parameterIndex, + new java.sql.Timestamp(parameterAsDate + .getTime())); + } + + break; + } + break; + + case Types.TIME: + + if (parameterObj instanceof String) { + java.text.DateFormat sdf = new java.text.SimpleDateFormat( + getDateTimePattern((String) parameterObj, true), Locale.US); + setTime(parameterIndex, new java.sql.Time(sdf.parse( + (String) parameterObj).getTime())); + } else if (parameterObj instanceof Timestamp) { + Timestamp xT = (Timestamp) parameterObj; + setTime(parameterIndex, new java.sql.Time(xT.getTime())); + } else { + setTime(parameterIndex, (java.sql.Time) parameterObj); + } + + break; + + case Types.OTHER: + setSerializableObject(parameterIndex, parameterObj); + + break; + + default: + throw SQLError.createSQLException(Messages + .getString("PreparedStatement.16"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - - break; - - case Types.TIME: - - if (parameterObj instanceof String) { - java.text.DateFormat sdf = new java.text.SimpleDateFormat( - getDateTimePattern((String) parameterObj, true), Locale.US); - setTime(parameterIndex, new java.sql.Time(sdf.parse( - (String) parameterObj).getTime())); - } else if (parameterObj instanceof Timestamp) { - Timestamp xT = (Timestamp) parameterObj; - setTime(parameterIndex, new java.sql.Time(xT.getTime())); - } else { - setTime(parameterIndex, (java.sql.Time) parameterObj); + } catch (Exception ex) { + if (ex instanceof SQLException) { + throw (SQLException) ex; } - - break; - - case Types.OTHER: - setSerializableObject(parameterIndex, parameterObj); - - break; - - default: - throw SQLError.createSQLException(Messages - .getString("PreparedStatement.16"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); + + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("PreparedStatement.17") //$NON-NLS-1$ + + parameterObj.getClass().toString() + + Messages.getString("PreparedStatement.18") //$NON-NLS-1$ + + ex.getClass().getName() + + Messages.getString("PreparedStatement.19") + ex.getMessage(), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + + sqlEx.initCause(ex); + + throw sqlEx; } - } catch (Exception ex) { - if (ex instanceof SQLException) { - throw (SQLException) ex; - } - - throw SQLError.createSQLException( - Messages.getString("PreparedStatement.17") //$NON-NLS-1$ - + parameterObj.getClass().toString() - + Messages.getString("PreparedStatement.18") //$NON-NLS-1$ - + ex.getClass().getName() - + Messages.getString("PreparedStatement.19") + ex.getMessage(), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); } } } @@ -3338,7 +4237,7 @@ return batchedParamIndex; } - + /** * JDBC 2.0 Set a REF(<structured-type>) parameter. * @@ -3353,39 +4252,11 @@ * DOCUMENT ME! */ public void setRef(int i, Ref x) throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } - /** - * Sets the concurrency for result sets generated by this statement - * - * @param concurrencyFlag - * DOCUMENT ME! - */ - void setResultSetConcurrency(int concurrencyFlag) { - this.resultSetConcurrency = concurrencyFlag; - } /** - * Sets the result set type for result sets generated by this statement - * - * @param typeFlag - * DOCUMENT ME! - */ - void setResultSetType(int typeFlag) { - this.resultSetType = typeFlag; - } - - /** - * DOCUMENT ME! - * - * @param retrieveGeneratedKeys - */ - protected void setRetrieveGeneratedKeys(boolean retrieveGeneratedKeys) { - this.retrieveGeneratedKeys = retrieveGeneratedKeys; - } - - /** * Sets the value for the placeholder as a serialized Java object (used by * various forms of setObject() * @@ -3411,10 +4282,14 @@ byte[] buf = bytesOut.toByteArray(); ByteArrayInputStream bytesIn = new ByteArrayInputStream(buf); setBinaryStream(parameterIndex, bytesIn, buf.length); + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.BINARY; } catch (Exception ex) { - throw SQLError.createSQLException(Messages.getString("PreparedStatement.54") //$NON-NLS-1$ + SQLException sqlEx = SQLError.createSQLException(Messages.getString("PreparedStatement.54") //$NON-NLS-1$ + ex.getClass().getName(), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; } } @@ -3432,6 +4307,8 @@ */ public void setShort(int parameterIndex, short x) throws SQLException { setInternal(parameterIndex, String.valueOf(x)); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.SMALLINT; } /** @@ -3448,184 +4325,222 @@ * if a database access error occurs */ public void setString(int parameterIndex, String x) throws SQLException { - // if the passed string is null, then set this column to null - if (x == null) { - setNull(parameterIndex, Types.CHAR); - } else { - checkClosed(); - - int stringLength = x.length(); - - if (this.connection.isNoBackslashEscapesSet()) { - // Scan for any nasty chars - - boolean needsHexEscape = false; - - for (int i = 0; i < stringLength; ++i) { - char c = x.charAt(i); - - switch (c) { - case 0: /* Must be escaped for 'mysql' */ - - needsHexEscape = true; - break; - - case '\n': /* Must be escaped for logs */ - needsHexEscape = true; - - break; - - case '\r': - needsHexEscape = true; - break; - - case '\\': - needsHexEscape = true; - - break; - - case '\'': - needsHexEscape = true; - - break; - - case '"': /* Better safe than sorry */ - needsHexEscape = true; - - break; - - case '\032': /* This gives problems on Win32 */ - needsHexEscape = true; - break; + synchronized (checkClosed().getConnectionMutex()) { + // if the passed string is null, then set this column to null + if (x == null) { + setNull(parameterIndex, Types.CHAR); + } else { + checkClosed(); + + int stringLength = x.length(); + + if (this.connection.isNoBackslashEscapesSet()) { + // Scan for any nasty chars + + boolean needsHexEscape = isEscapeNeededForString(x, + stringLength); + + if (!needsHexEscape) { + byte[] parameterAsBytes = null; + + StringBuffer quotedString = new StringBuffer(x.length() + 2); + quotedString.append('\''); + quotedString.append(x); + quotedString.append('\''); + + if (!this.isLoadDataQuery) { + parameterAsBytes = StringUtils.getBytes(quotedString.toString(), + this.charConverter, this.charEncoding, + this.connection.getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor()); + } else { + // Send with platform character encoding + parameterAsBytes = StringUtils.getBytes(quotedString.toString()); + } + + setInternal(parameterIndex, parameterAsBytes); + } else { + byte[] parameterAsBytes = null; + + if (!this.isLoadDataQuery) { + parameterAsBytes = StringUtils.getBytes(x, + this.charConverter, this.charEncoding, + this.connection.getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor()); + } else { + // Send with platform character encoding + parameterAsBytes = StringUtils.getBytes(x); + } + + setBytes(parameterIndex, parameterAsBytes); } - - if (needsHexEscape) { - break; // no need to scan more - } + + return; } - + + String parameterAsString = x; + boolean needsQuoted = true; - - if (!needsHexEscape) { - byte[] parameterAsBytes = null; - - StringBuffer quotedString = new StringBuffer(x.length() + 2); - quotedString.append('\''); - quotedString.append(x); - quotedString.append('\''); + if (this.isLoadDataQuery || isEscapeNeededForString(x, stringLength)) { + needsQuoted = false; // saves an allocation later - if (!this.isLoadDataQuery) { - parameterAsBytes = StringUtils.getBytes(quotedString.toString(), - this.charConverter, this.charEncoding, - this.connection.getServerCharacterEncoding(), - this.connection.parserKnowsUnicode()); - } else { - // Send with platform character encoding - parameterAsBytes = quotedString.toString().getBytes(); - } + StringBuffer buf = new StringBuffer((int) (x.length() * 1.1)); - setInternal(parameterIndex, parameterAsBytes); - } else { - byte[] parameterAsBytes = null; - - if (!this.isLoadDataQuery) { - parameterAsBytes = StringUtils.getBytes(x, - this.charConverter, this.charEncoding, - this.connection.getServerCharacterEncoding(), - this.connection.parserKnowsUnicode()); + buf.append('\''); + + // + // Note: buf.append(char) is _faster_ than + // appending in blocks, because the block + // append requires a System.arraycopy().... + // go figure... + // + + for (int i = 0; i < stringLength; ++i) { + char c = x.charAt(i); + + switch (c) { + case 0: /* Must be escaped for 'mysql' */ + buf.append('\\'); + buf.append('0'); + + break; + + case '\n': /* Must be escaped for logs */ + buf.append('\\'); + buf.append('n'); + + break; + + case '\r': + buf.append('\\'); + buf.append('r'); + + break; + + case '\\': + buf.append('\\'); + buf.append('\\'); + + break; + + case '\'': + buf.append('\\'); + buf.append('\''); + + break; + + case '"': /* Better safe than sorry */ + if (this.usingAnsiMode) { + buf.append('\\'); + } + + buf.append('"'); + + break; + + case '\032': /* This gives problems on Win32 */ + buf.append('\\'); + buf.append('Z'); + + break; + + case '\u00a5': + case '\u20a9': + // escape characters interpreted as backslash by mysql + if(charsetEncoder != null) { + CharBuffer cbuf = CharBuffer.allocate(1); + ByteBuffer bbuf = ByteBuffer.allocate(1); + cbuf.put(c); + cbuf.position(0); + charsetEncoder.encode(cbuf, bbuf, true); + if(bbuf.get(0) == '\\') { + buf.append('\\'); + } + } + // fall through + + default: + buf.append(c); + } + } + + buf.append('\''); + + parameterAsString = buf.toString(); + } + + byte[] parameterAsBytes = null; + + if (!this.isLoadDataQuery) { + if (needsQuoted) { + parameterAsBytes = StringUtils.getBytesWrapped(parameterAsString, + '\'', '\'', this.charConverter, this.charEncoding, this.connection + .getServerCharacterEncoding(), this.connection + .parserKnowsUnicode(), getExceptionInterceptor()); } else { - // Send with platform character encoding - parameterAsBytes = x.getBytes(); + parameterAsBytes = StringUtils.getBytes(parameterAsString, + this.charConverter, this.charEncoding, this.connection + .getServerCharacterEncoding(), this.connection + .parserKnowsUnicode(), getExceptionInterceptor()); } - - setBytes(parameterIndex, parameterAsBytes); + } else { + // Send with platform character encoding + parameterAsBytes = StringUtils.getBytes(parameterAsString); } - - return; + + setInternal(parameterIndex, parameterAsBytes); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.VARCHAR; } + } + } - StringBuffer buf = new StringBuffer((int) (x.length() * 1.1)); - buf.append('\''); + private boolean isEscapeNeededForString(String x, int stringLength) { + boolean needsHexEscape = false; - // - // Note: buf.append(char) is _faster_ than - // appending in blocks, because the block - // append requires a System.arraycopy().... - // go figure... - // + for (int i = 0; i < stringLength; ++i) { + char c = x.charAt(i); - for (int i = 0; i < stringLength; ++i) { - char c = x.charAt(i); + switch (c) { + case 0: /* Must be escaped for 'mysql' */ - switch (c) { - case 0: /* Must be escaped for 'mysql' */ - buf.append('\\'); - buf.append('0'); + needsHexEscape = true; + break; - break; + case '\n': /* Must be escaped for logs */ + needsHexEscape = true; - case '\n': /* Must be escaped for logs */ - buf.append('\\'); - buf.append('n'); + break; - break; + case '\r': + needsHexEscape = true; + break; - case '\r': - buf.append('\\'); - buf.append('r'); + case '\\': + needsHexEscape = true; - break; + break; - case '\\': - buf.append('\\'); - buf.append('\\'); + case '\'': + needsHexEscape = true; - break; + break; - case '\'': - buf.append('\\'); - buf.append('\''); + case '"': /* Better safe than sorry */ + needsHexEscape = true; - break; + break; - case '"': /* Better safe than sorry */ - if (this.usingAnsiMode) { - buf.append('\\'); - } - - buf.append('"'); - - break; - - case '\032': /* This gives problems on Win32 */ - buf.append('\\'); - buf.append('Z'); - - break; - - default: - buf.append(c); - } + case '\032': /* This gives problems on Win32 */ + needsHexEscape = true; + break; } - buf.append('\''); - - String parameterAsString = buf.toString(); - - byte[] parameterAsBytes = null; - - if (!this.isLoadDataQuery) { - parameterAsBytes = StringUtils.getBytes(parameterAsString, - this.charConverter, this.charEncoding, this.connection - .getServerCharacterEncoding(), this.connection - .parserKnowsUnicode()); - } else { - // Send with platform character encoding - parameterAsBytes = parameterAsString.getBytes(); + if (needsHexEscape) { + break; // no need to scan more } - - setInternal(parameterIndex, parameterAsBytes); } + return needsHexEscape; } /** @@ -3661,7 +4576,7 @@ */ public void setTime(int parameterIndex, Time x) throws java.sql.SQLException { - setTimeInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false); + setTimeInternal(parameterIndex, x, null, Util.getDefaultTimeZone(), false); } /** @@ -3682,22 +4597,30 @@ private void setTimeInternal(int parameterIndex, Time x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws java.sql.SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.TIME); - } else { - checkClosed(); - - Calendar sessionCalendar = getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar) { - x = TimeUtil.changeTimezone(this.connection, - sessionCalendar, - targetCalendar, - x, tz, this.connection - .getServerTimezoneTZ(), rollForward); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.TIME); + } else { + checkClosed(); + + if (!this.useLegacyDatetimeCode) { + newSetTimeInternal(parameterIndex, x, targetCalendar); + } else { + Calendar sessionCalendar = getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + x = TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + x, tz, this.connection + .getServerTimezoneTZ(), rollForward); + } + + setInternal(parameterIndex, "'" + x.toString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.TIME; } - - setInternal(parameterIndex, "'" + x.toString() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } } @@ -3734,7 +4657,7 @@ */ public void setTimestamp(int parameterIndex, Timestamp x) throws java.sql.SQLException { - setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false); + setTimestampInternal(parameterIndex, x, null, Util.getDefaultTimeZone(), false); } /** @@ -3754,113 +4677,211 @@ private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.TIMESTAMP); - } else { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.TIMESTAMP); + } else { + checkClosed(); + + if (!this.useLegacyDatetimeCode) { + newSetTimestampInternal(parameterIndex, x, targetCalendar); + } else { + Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? + this.connection.getUtcCalendar() : + getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + x = TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + x, tz, this.connection + .getServerTimezoneTZ(), rollForward); + } + + if (this.connection.getUseSSPSCompatibleTimezoneShift()) { + doSSPSCompatibleTimezoneShift(parameterIndex, x, sessionCalendar); + } else { + synchronized (this) { + if (this.tsdf == null) { + this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); //$NON-NLS-1$ + } + + StringBuffer buf = new StringBuffer(); + buf.append(this.tsdf.format(x)); + + if (this.serverSupportsFracSecs) { + int nanos = x.getNanos(); + + if (nanos != 0) { + buf.append('.'); + buf.append(TimeUtil.formatNanos(nanos, this.serverSupportsFracSecs, true)); + } + } + + buf.append('\''); + + setInternal(parameterIndex, buf.toString()); // SimpleDateFormat is not + // thread-safe + } + } + } + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.TIMESTAMP; + } + } + } + + private void newSetTimestampInternal(int parameterIndex, + Timestamp x, Calendar targetCalendar) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.tsdf == null) { + this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); //$NON-NLS-1$ + } String timestampString = null; - Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? - this.connection.getUtcCalendar() : - getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar) { - x = TimeUtil.changeTimezone(this.connection, - sessionCalendar, - targetCalendar, - x, tz, this.connection - .getServerTimezoneTZ(), rollForward); + if (targetCalendar != null) { + targetCalendar.setTime(x); + this.tsdf.setTimeZone(targetCalendar.getTimeZone()); + + timestampString = this.tsdf.format(x); + } else { + this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ()); + timestampString = this.tsdf.format(x); } - + + StringBuffer buf = new StringBuffer(); + buf.append(timestampString); + buf.append('.'); + buf.append(TimeUtil.formatNanos(x.getNanos(), this.serverSupportsFracSecs, true)); + buf.append('\''); - if (this.connection.getUseSSPSCompatibleTimezoneShift()) { - doSSPSCompatibleTimezoneShift(parameterIndex, x, sessionCalendar); - } else { + setInternal(parameterIndex, buf.toString()); + } + } + + private void newSetTimeInternal(int parameterIndex, + Time x, Calendar targetCalendar) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.tdf == null) { + this.tdf = new SimpleDateFormat("''HH:mm:ss''", Locale.US); //$NON-NLS-1$ - if (this.tsdf == null) { - this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss''", Locale.US); //$NON-NLS-1$ - } + } + + String timeString = null; + + if (targetCalendar != null) { + targetCalendar.setTime(x); + this.tdf.setTimeZone(targetCalendar.getTimeZone()); - timestampString = this.tsdf.format(x); - - setInternal(parameterIndex, timestampString); // SimpleDateFormat is not - // thread-safe + timeString = this.tdf.format(x); + } else { + this.tdf.setTimeZone(this.connection.getServerTimezoneTZ()); + timeString = this.tdf.format(x); } + + setInternal(parameterIndex, timeString); } } + + private void newSetDateInternal(int parameterIndex, + Date x, Calendar targetCalendar) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.ddf == null) { + this.ddf = new SimpleDateFormat("''yyyy-MM-dd''", Locale.US); //$NON-NLS-1$ + } + + String timeString = null; + + if (targetCalendar != null) { + targetCalendar.setTime(x); + this.ddf.setTimeZone(targetCalendar.getTimeZone()); + + timeString = this.ddf.format(x); + } else { + this.ddf.setTimeZone(this.connection.getServerTimezoneTZ()); + timeString = this.ddf.format(x); + } + + setInternal(parameterIndex, timeString); + } + } private void doSSPSCompatibleTimezoneShift(int parameterIndex, Timestamp x, Calendar sessionCalendar) throws SQLException { - Calendar sessionCalendar2 = (this.connection - .getUseJDBCCompliantTimezoneShift()) ? this.connection - .getUtcCalendar() - : getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar2) { - java.util.Date oldTime = sessionCalendar2.getTime(); - - try { - sessionCalendar2.setTime(x); - - int year = sessionCalendar2.get(Calendar.YEAR); - int month = sessionCalendar2.get(Calendar.MONTH) + 1; - int date = sessionCalendar2.get(Calendar.DAY_OF_MONTH); - - int hour = sessionCalendar2.get(Calendar.HOUR_OF_DAY); - int minute = sessionCalendar2.get(Calendar.MINUTE); - int seconds = sessionCalendar2.get(Calendar.SECOND); - - StringBuffer tsBuf = new StringBuffer(); - - tsBuf.append('\''); - tsBuf.append(year); - - tsBuf.append("-"); - - if (month < 10) { - tsBuf.append('0'); + synchronized (checkClosed().getConnectionMutex()) { + Calendar sessionCalendar2 = (this.connection + .getUseJDBCCompliantTimezoneShift()) ? this.connection + .getUtcCalendar() + : getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar2) { + java.util.Date oldTime = sessionCalendar2.getTime(); + + try { + sessionCalendar2.setTime(x); + + int year = sessionCalendar2.get(Calendar.YEAR); + int month = sessionCalendar2.get(Calendar.MONTH) + 1; + int date = sessionCalendar2.get(Calendar.DAY_OF_MONTH); + + int hour = sessionCalendar2.get(Calendar.HOUR_OF_DAY); + int minute = sessionCalendar2.get(Calendar.MINUTE); + int seconds = sessionCalendar2.get(Calendar.SECOND); + + StringBuffer tsBuf = new StringBuffer(); + + tsBuf.append('\''); + tsBuf.append(year); + + tsBuf.append("-"); + + if (month < 10) { + tsBuf.append('0'); + } + + tsBuf.append(month); + + tsBuf.append('-'); + + if (date < 10) { + tsBuf.append('0'); + } + + tsBuf.append(date); + + tsBuf.append(' '); + + if (hour < 10) { + tsBuf.append('0'); + } + + tsBuf.append(hour); + + tsBuf.append(':'); + + if (minute < 10) { + tsBuf.append('0'); + } + + tsBuf.append(minute); + + tsBuf.append(':'); + + if (seconds < 10) { + tsBuf.append('0'); + } + + tsBuf.append(seconds); + + tsBuf.append('.'); + tsBuf.append(TimeUtil.formatNanos(x.getNanos(), this.serverSupportsFracSecs, true)); + tsBuf.append('\''); + + setInternal(parameterIndex, tsBuf.toString()); + + } finally { + sessionCalendar.setTime(oldTime); } - - tsBuf.append(month); - - tsBuf.append('-'); - - if (date < 10) { - tsBuf.append('0'); - } - - tsBuf.append(date); - - tsBuf.append(' '); - - if (hour < 10) { - tsBuf.append('0'); - } - - tsBuf.append(hour); - - tsBuf.append(':'); - - if (minute < 10) { - tsBuf.append('0'); - } - - tsBuf.append(minute); - - tsBuf.append(':'); - - if (seconds < 10) { - tsBuf.append('0'); - } - - tsBuf.append(seconds); - - tsBuf.append('\''); - - setInternal(parameterIndex, tsBuf.toString()); - - } finally { - sessionCalendar.setTime(oldTime); } } } @@ -3895,6 +4916,8 @@ setNull(parameterIndex, java.sql.Types.VARCHAR); } else { setBinaryStream(parameterIndex, x, length); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.CLOB; } } @@ -3904,6 +4927,8 @@ public void setURL(int parameterIndex, URL arg) throws SQLException { if (arg != null) { setString(parameterIndex, arg.toString()); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.DATALINK; } else { setNull(parameterIndex, Types.CHAR); } @@ -3912,148 +4937,165 @@ private final void streamToBytes(Buffer packet, InputStream in, boolean escape, int streamLength, boolean useLength) throws SQLException { - try { - String connectionEncoding = this.connection.getEncoding(); - - boolean hexEscape = false; - - if (this.connection.isNoBackslashEscapesSet() - || (this.connection.getUseUnicode() - && connectionEncoding != null - && CharsetMapping.isMultibyteCharset(connectionEncoding) - && !this.connection.parserKnowsUnicode())) { - hexEscape = true; - } - - if (streamLength == -1) { - useLength = false; - } - - int bc = -1; - - if (useLength) { - bc = readblock(in, streamConvertBuf, streamLength); - } else { - bc = readblock(in, streamConvertBuf); - } - - int lengthLeftToRead = streamLength - bc; - - if (hexEscape) { - packet.writeStringNoNull("x"); - } else if (this.connection.getIO().versionMeetsMinimum(4, 1, 0)) { - packet.writeStringNoNull("_binary"); - } - - if (escape) { - packet.writeByte((byte) '\''); - } - - while (bc > 0) { - if (hexEscape) { - hexEscapeBlock(streamConvertBuf, packet, bc); - } else if (escape) { - escapeblockFast(streamConvertBuf, packet, bc); - } else { - packet.writeBytesNoNull(streamConvertBuf, 0, bc); + synchronized (checkClosed().getConnectionMutex()) { + try { + if (streamConvertBuf == null) { + streamConvertBuf = new byte[4096]; } - - if (useLength) { - bc = readblock(in, streamConvertBuf, lengthLeftToRead); - - if (bc > 0) { - lengthLeftToRead -= bc; + + String connectionEncoding = this.connection.getEncoding(); + + boolean hexEscape = false; + + try { + if (this.connection.isNoBackslashEscapesSet() + || (this.connection.getUseUnicode() + && connectionEncoding != null + && CharsetMapping.isMultibyteCharset(connectionEncoding) + && !this.connection.parserKnowsUnicode())) { + hexEscape = true; } + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + + if (streamLength == -1) { + useLength = false; + } + + int bc = -1; + + if (useLength) { + bc = readblock(in, streamConvertBuf, streamLength); } else { bc = readblock(in, streamConvertBuf); } - } - - if (escape) { - packet.writeByte((byte) '\''); - } - } finally { - if (this.connection.getAutoClosePStmtStreams()) { - try { - in.close(); - } catch (IOException ioEx) { - ; + + int lengthLeftToRead = streamLength - bc; + + if (hexEscape) { + packet.writeStringNoNull("x"); + } else if (this.connection.getIO().versionMeetsMinimum(4, 1, 0)) { + packet.writeStringNoNull("_binary"); } - - in = null; + + if (escape) { + packet.writeByte((byte) '\''); + } + + while (bc > 0) { + if (hexEscape) { + hexEscapeBlock(streamConvertBuf, packet, bc); + } else if (escape) { + escapeblockFast(streamConvertBuf, packet, bc); + } else { + packet.writeBytesNoNull(streamConvertBuf, 0, bc); + } + + if (useLength) { + bc = readblock(in, streamConvertBuf, lengthLeftToRead); + + if (bc > 0) { + lengthLeftToRead -= bc; + } + } else { + bc = readblock(in, streamConvertBuf); + } + } + + if (escape) { + packet.writeByte((byte) '\''); + } + } finally { + if (this.connection.getAutoClosePStmtStreams()) { + try { + in.close(); + } catch (IOException ioEx) { + ; + } + + in = null; + } } } } private final byte[] streamToBytes(InputStream in, boolean escape, int streamLength, boolean useLength) throws SQLException { - try { - if (streamLength == -1) { - useLength = false; - } - - ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); - - int bc = -1; - - if (useLength) { - bc = readblock(in, this.streamConvertBuf, streamLength); - } else { - bc = readblock(in, this.streamConvertBuf); - } - - int lengthLeftToRead = streamLength - bc; - - if (escape) { - if (this.connection.versionMeetsMinimum(4, 1, 0)) { - bytesOut.write('_'); - bytesOut.write('b'); - bytesOut.write('i'); - bytesOut.write('n'); - bytesOut.write('a'); - bytesOut.write('r'); - bytesOut.write('y'); + synchronized (checkClosed().getConnectionMutex()) { + try { + if (streamConvertBuf == null) { + streamConvertBuf = new byte[4096]; } - - bytesOut.write('\''); - } - - while (bc > 0) { - if (escape) { - escapeblockFast(this.streamConvertBuf, bytesOut, bc); - } else { - bytesOut.write(this.streamConvertBuf, 0, bc); + if (streamLength == -1) { + useLength = false; } - + + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + + int bc = -1; + if (useLength) { - bc = readblock(in, this.streamConvertBuf, lengthLeftToRead); - - if (bc > 0) { - lengthLeftToRead -= bc; - } + bc = readblock(in, this.streamConvertBuf, streamLength); } else { bc = readblock(in, this.streamConvertBuf); } - } - - if (escape) { - bytesOut.write('\''); - } - - return bytesOut.toByteArray(); - } finally { - if (this.connection.getAutoClosePStmtStreams()) { - try { - in.close(); - } catch (IOException ioEx) { - ; + + int lengthLeftToRead = streamLength - bc; + + if (escape) { + if (this.connection.versionMeetsMinimum(4, 1, 0)) { + bytesOut.write('_'); + bytesOut.write('b'); + bytesOut.write('i'); + bytesOut.write('n'); + bytesOut.write('a'); + bytesOut.write('r'); + bytesOut.write('y'); + } + + bytesOut.write('\''); } - - in = null; + + while (bc > 0) { + if (escape) { + escapeblockFast(this.streamConvertBuf, bytesOut, bc); + } else { + bytesOut.write(this.streamConvertBuf, 0, bc); + } + + if (useLength) { + bc = readblock(in, this.streamConvertBuf, lengthLeftToRead); + + if (bc > 0) { + lengthLeftToRead -= bc; + } + } else { + bc = readblock(in, this.streamConvertBuf); + } + } + + if (escape) { + bytesOut.write('\''); + } + + return bytesOut.toByteArray(); + } finally { + if (this.connection.getAutoClosePStmtStreams()) { + try { + in.close(); + } catch (IOException ioEx) { + ; + } + + in = null; + } } } } - + /** * Returns this PreparedStatement represented as a string. * @@ -4072,7 +5114,8 @@ return buf.toString(); } - + + /** * For calling stored functions, this will be -1 as we don't really count * the first '?' parameter marker, it's only syntax, but JDBC counts it @@ -4083,4 +5126,510 @@ protected int getParameterIndexOffset() { return 0; } + + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + setAsciiStream(parameterIndex, x, -1); + } + + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + setAsciiStream(parameterIndex, x, (int)length); + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.CLOB; + } + + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + setBinaryStream(parameterIndex, x, -1); + } + + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + setBinaryStream(parameterIndex, x, (int)length); + } + + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + setBinaryStream(parameterIndex, inputStream); + } + + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + setCharacterStream(parameterIndex, reader, -1); + } + + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + setCharacterStream(parameterIndex, reader, (int)length); + + } + + public void setClob(int parameterIndex, Reader reader) throws SQLException { + setCharacterStream(parameterIndex, reader); + + } + + public void setClob(int parameterIndex, Reader reader, long length) + throws SQLException { + setCharacterStream(parameterIndex, reader, length); + } + + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + setNCharacterStream(parameterIndex, value, -1); + } + + /** + * Set a parameter to a Java String value. The driver converts this to a SQL + * VARCHAR or LONGVARCHAR value with introducer _utf8 (depending on the + * arguments size relative to the driver's limits on VARCHARs) when it sends + * it to the database. If charset is set as utf8, this method just call setString. + * + * @param parameterIndex + * the first parameter is 1... + * @param x + * the parameter value + * + * @exception SQLException + * if a database access error occurs + */ + public void setNString(int parameterIndex, String x) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.charEncoding.equalsIgnoreCase("UTF-8") + || this.charEncoding.equalsIgnoreCase("utf8")) { + setString(parameterIndex, x); + return; + } + + // if the passed string is null, then set this column to null + if (x == null) { + setNull(parameterIndex, java.sql.Types.CHAR); + } else { + int stringLength = x.length(); + // Ignore sql_mode=NO_BACKSLASH_ESCAPES in current implementation. + + // Add introducer _utf8 for NATIONAL CHARACTER + StringBuffer buf = new StringBuffer((int) (x.length() * 1.1 + 4)); + buf.append("_utf8"); + buf.append('\''); + + // + // Note: buf.append(char) is _faster_ than + // appending in blocks, because the block + // append requires a System.arraycopy().... + // go figure... + // + + for (int i = 0; i < stringLength; ++i) { + char c = x.charAt(i); + + switch (c) { + case 0: /* Must be escaped for 'mysql' */ + buf.append('\\'); + buf.append('0'); + + break; + + case '\n': /* Must be escaped for logs */ + buf.append('\\'); + buf.append('n'); + + break; + + case '\r': + buf.append('\\'); + buf.append('r'); + + break; + + case '\\': + buf.append('\\'); + buf.append('\\'); + + break; + + case '\'': + buf.append('\\'); + buf.append('\''); + + break; + + case '"': /* Better safe than sorry */ + if (this.usingAnsiMode) { + buf.append('\\'); + } + + buf.append('"'); + + break; + + case '\032': /* This gives problems on Win32 */ + buf.append('\\'); + buf.append('Z'); + + break; + + default: + buf.append(c); + } + } + + buf.append('\''); + + String parameterAsString = buf.toString(); + + byte[] parameterAsBytes = null; + + if (!this.isLoadDataQuery) { + parameterAsBytes = StringUtils.getBytes(parameterAsString, + this.connection.getCharsetConverter("UTF-8"), "UTF-8", + this.connection.getServerCharacterEncoding(), + this.connection.parserKnowsUnicode(), getExceptionInterceptor()); + } else { + // Send with platform character encoding + parameterAsBytes = StringUtils.getBytes(parameterAsString); + } + + setInternal(parameterIndex, parameterAsBytes); + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = -9; /* Types.NVARCHAR */ + } + } + } + + /** + * JDBC 2.0 When a very large UNICODE value is input to a LONGVARCHAR + * parameter, it may be more practical to send it via a java.io.Reader. JDBC + * will read the data from the stream as needed, until it reaches + * end-of-file. The JDBC driver will do any necessary conversion from + * UNICODE to the database char format. + * + *

+ * Note: This stream object can either be a standard Java stream + * object or your own subclass that implements the standard interface. + *

+ * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param reader + * the java reader which contains the UNICODE data + * @param length + * the number of characters in the stream + * + * @exception SQLException + * if a database-access error occurs. + */ + public void setNCharacterStream(int parameterIndex, Reader reader, + long length) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + try { + if (reader == null) { + setNull(parameterIndex, java.sql.Types.LONGVARCHAR); + + } else { + char[] c = null; + int len = 0; + + boolean useLength = this.connection + .getUseStreamLengthsInPrepStmts(); + + // Ignore "clobCharacterEncoding" because utf8 should be used this time. + + if (useLength && (length != -1)) { + c = new char[(int) length]; // can't take more than Integer.MAX_VALUE + + int numCharsRead = readFully(reader, c, (int) length); // blocks + // until + // all + // read + setNString(parameterIndex, new String(c, 0, numCharsRead)); + + } else { + c = new char[4096]; + + StringBuffer buf = new StringBuffer(); + + while ((len = reader.read(c)) != -1) { + buf.append(c, 0, len); + } + + setNString(parameterIndex, buf.toString()); + } + + this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = 2011; /* Types.NCLOB */ + } + } catch (java.io.IOException ioEx) { + throw SQLError.createSQLException(ioEx.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + } + + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + setNCharacterStream(parameterIndex, reader); + } + + /** + * JDBC 4.0 Set a NCLOB parameter. + * + * @param parameterIndex + * the first parameter is 1, the second is 2, ... + * @param reader + * the java reader which contains the UNICODE data + * @param length + * the number of characters in the stream + * + * @throws SQLException + * if a database error occurs + */ + public void setNClob(int parameterIndex, Reader reader, long length) + throws SQLException { + if (reader == null) { + setNull(parameterIndex, java.sql.Types.LONGVARCHAR); + } else { + setNCharacterStream(parameterIndex, reader, length); + } + } + + public ParameterBindings getParameterBindings() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return new EmulatedPreparedStatementBindings(); + } + } + + class EmulatedPreparedStatementBindings implements ParameterBindings { + + private ResultSetImpl bindingsAsRs; + private boolean[] parameterIsNull; + + EmulatedPreparedStatementBindings() throws SQLException { + List rows = new ArrayList(); + parameterIsNull = new boolean[parameterCount]; + System + .arraycopy(isNull, 0, this.parameterIsNull, 0, + parameterCount); + byte[][] rowData = new byte[parameterCount][]; + Field[] typeMetadata = new Field[parameterCount]; + + for (int i = 0; i < parameterCount; i++) { + if (batchCommandIndex == -1) + rowData[i] = getBytesRepresentation(i); + else + rowData[i] = getBytesRepresentationForBatch(i, batchCommandIndex); + + int charsetIndex = 0; + + if (parameterTypes[i] == Types.BINARY + || parameterTypes[i] == Types.BLOB) { + charsetIndex = 63; + } else { + try { + String mysqlEncodingName = CharsetMapping + .getMysqlEncodingForJavaEncoding(connection + .getEncoding(), connection); + charsetIndex = CharsetMapping + .getCharsetIndexForMysqlEncodingName(mysqlEncodingName); + } catch (SQLException ex) { + throw ex; + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } + } + + Field parameterMetadata = new Field(null, "parameter_" + + (i + 1), charsetIndex, parameterTypes[i], + rowData[i].length); + parameterMetadata.setConnection(connection); + typeMetadata[i] = parameterMetadata; + } + + rows.add(new ByteArrayRow(rowData, getExceptionInterceptor())); + + this.bindingsAsRs = new ResultSetImpl(connection.getCatalog(), + typeMetadata, new RowDataStatic(rows), connection, null); + this.bindingsAsRs.next(); + } + + public Array getArray(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getArray(parameterIndex); + } + + public InputStream getAsciiStream(int parameterIndex) + throws SQLException { + return this.bindingsAsRs.getAsciiStream(parameterIndex); + } + + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getBigDecimal(parameterIndex); + } + + public InputStream getBinaryStream(int parameterIndex) + throws SQLException { + return this.bindingsAsRs.getBinaryStream(parameterIndex); + } + + public java.sql.Blob getBlob(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getBlob(parameterIndex); + } + + public boolean getBoolean(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getBoolean(parameterIndex); + } + + public byte getByte(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getByte(parameterIndex); + } + + public byte[] getBytes(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getBytes(parameterIndex); + } + + public Reader getCharacterStream(int parameterIndex) + throws SQLException { + return this.bindingsAsRs.getCharacterStream(parameterIndex); + } + + public java.sql.Clob getClob(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getClob(parameterIndex); + } + + public Date getDate(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getDate(parameterIndex); + } + + public double getDouble(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getDouble(parameterIndex); + } + + public float getFloat(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getFloat(parameterIndex); + } + + public int getInt(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getInt(parameterIndex); + } + + public long getLong(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getLong(parameterIndex); + } + + public Reader getNCharacterStream(int parameterIndex) + throws SQLException { + return this.bindingsAsRs.getCharacterStream(parameterIndex); + } + + public Reader getNClob(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getCharacterStream(parameterIndex); + } + + public Object getObject(int parameterIndex) throws SQLException { + checkBounds(parameterIndex, 0); + + if (parameterIsNull[parameterIndex - 1]) { + return null; + } + + // we can't rely on the default mapping for JDBC's + // ResultSet.getObject() for numerics, they're not one-to-one with + // PreparedStatement.setObject + + switch (parameterTypes[parameterIndex - 1]) { + case Types.TINYINT: + return Byte.valueOf(getByte(parameterIndex)); + case Types.SMALLINT: + return Short.valueOf(getShort(parameterIndex)); + case Types.INTEGER: + return Integer.valueOf(getInt(parameterIndex)); + case Types.BIGINT: + return Long.valueOf(getLong(parameterIndex)); + case Types.FLOAT: + return Float.valueOf(getFloat(parameterIndex)); + case Types.DOUBLE: + return Double.valueOf(getDouble(parameterIndex)); + default: + return this.bindingsAsRs.getObject(parameterIndex); + } + } + + public Ref getRef(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getRef(parameterIndex); + } + + public short getShort(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getShort(parameterIndex); + } + + public String getString(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getString(parameterIndex); + } + + public Time getTime(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getTime(parameterIndex); + } + + public Timestamp getTimestamp(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getTimestamp(parameterIndex); + } + + public URL getURL(int parameterIndex) throws SQLException { + return this.bindingsAsRs.getURL(parameterIndex); + } + + public boolean isNull(int parameterIndex) throws SQLException { + checkBounds(parameterIndex, 0); + + return this.parameterIsNull[parameterIndex -1]; + } + } + + public String getPreparedSql() { + try { + synchronized (checkClosed().getConnectionMutex()) { + if (this.rewrittenBatchSize == 0) { + return this.originalSql; + } + + try { + return this.parseInfo.getSqlForBatch(this.parseInfo); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: evolve public interface + } + } + + public int getUpdateCount() throws SQLException { + int count = super.getUpdateCount(); + + if (containsOnDuplicateKeyUpdateInSQL() && + this.compensateForOnDuplicateKeyUpdate) { + if (count == 2 || count == 0) { + count = 1; + } + } + + return count; + } + + protected static boolean canRewrite(String sql, boolean isOnDuplicateKeyUpdate, int locationOfOnDuplicateKeyUpdate, int statementStartPos) { + // Needs to be INSERT, can't have INSERT ... SELECT or + // INSERT ... ON DUPLICATE KEY UPDATE with an id=LAST_INSERT_ID(...) + + boolean rewritableOdku = true; + + if (isOnDuplicateKeyUpdate) { + int updateClausePos = StringUtils.indexOfIgnoreCase( + locationOfOnDuplicateKeyUpdate, sql, " UPDATE "); + + if (updateClausePos != -1) { + rewritableOdku = StringUtils + .indexOfIgnoreCaseRespectMarker(updateClausePos, + sql, "LAST_INSERT_ID", "\"'`", "\"'`", + false) == -1; + } + } + + return StringUtils + .startsWithIgnoreCaseAndWs(sql, "INSERT", + statementStartPos) + && StringUtils.indexOfIgnoreCaseRespectMarker( + statementStartPos, sql, "SELECT", "\"'`", + "\"'`", false) == -1 && rewritableOdku; + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ProfilerEventHandlerFactory.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ProfilerEventHandlerFactory.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ProfilerEventHandlerFactory.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,81 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + +import com.mysql.jdbc.log.Log; +import com.mysql.jdbc.profiler.ProfilerEventHandler; + +/** + * @author mmatthew + */ +public class ProfilerEventHandlerFactory { + + private Connection ownerConnection = null; + + protected Log log = null; + + /** + * Returns the ProfilerEventHandlerFactory that handles profiler events for the given + * connection. + * + * @param conn + * the connection to handle events for + * @return the ProfilerEventHandlerFactory that handles profiler events + */ + public static synchronized ProfilerEventHandler getInstance(MySQLConnection conn) throws SQLException { + ProfilerEventHandler handler = conn.getProfilerEventHandlerInstance(); + + if (handler == null) { + handler = (ProfilerEventHandler)Util.getInstance(conn.getProfilerEventHandler(), new Class[0], new Object[0], conn.getExceptionInterceptor()); + + // we do it this way to not require + // exposing the connection properties + // for all who utilize it + conn.initializeExtension(handler); + conn.setProfilerEventHandlerInstance(handler); + } + + return handler; + } + + public static synchronized void removeInstance(MySQLConnection conn) { + ProfilerEventHandler handler = conn.getProfilerEventHandlerInstance(); + + if (handler != null) { + handler.destroy(); + } + } + + private ProfilerEventHandlerFactory(Connection conn) { + this.ownerConnection = conn; + + try { + this.log = this.ownerConnection.getLog(); + } catch (SQLException sqlEx) { + throw new RuntimeException("Unable to get logger from connection"); + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/RandomBalanceStrategy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/RandomBalanceStrategy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/RandomBalanceStrategy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,132 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +public class RandomBalanceStrategy implements BalanceStrategy { + + public RandomBalanceStrategy() { + } + + public void destroy() { + // we don't have anything to clean up + } + + public void init(Connection conn, Properties props) throws SQLException { + // we don't have anything to initialize + } + + public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, + List configuredHosts, Map liveConnections, long[] responseTimes, + int numRetries) throws SQLException { + int numHosts = configuredHosts.size(); + + SQLException ex = null; + + List whiteList = new ArrayList(numHosts); + whiteList.addAll(configuredHosts); + + Map blackList = proxy.getGlobalBlacklist(); + + whiteList.removeAll(blackList.keySet()); + + Map whiteListMap = this.getArrayIndexMap(whiteList); + + + for (int attempts = 0; attempts < numRetries;) { + int random = (int) Math.floor((Math.random() * whiteList.size())); + if(whiteList.size() == 0){ + throw SQLError.createSQLException("No hosts configured", null); + } + + String hostPortSpec = whiteList.get(random); + + ConnectionImpl conn = liveConnections.get(hostPortSpec); + + if (conn == null) { + try { + conn = proxy.createConnectionForHost(hostPortSpec); + } catch (SQLException sqlEx) { + ex = sqlEx; + + if (proxy.shouldExceptionTriggerFailover(sqlEx)) { + + Integer whiteListIndex = whiteListMap.get(hostPortSpec); + + // exclude this host from being picked again + if (whiteListIndex != null) { + whiteList.remove(whiteListIndex.intValue()); + whiteListMap = this.getArrayIndexMap(whiteList); + } + proxy.addToGlobalBlacklist( hostPortSpec ); + + if (whiteList.size() == 0) { + attempts++; + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + + // start fresh + whiteListMap = new HashMap(numHosts); + whiteList.addAll(configuredHosts); + blackList = proxy.getGlobalBlacklist(); + + whiteList.removeAll(blackList.keySet()); + whiteListMap = this.getArrayIndexMap(whiteList); + } + + continue; + } + + throw sqlEx; + } + } + + return conn; + } + + if (ex != null) { + throw ex; + } + + return null; // we won't get here, compiler can't tell + } + + private Map getArrayIndexMap(List l) { + Map m = new HashMap(l.size()); + for (int i = 0; i < l.size(); i++) { + m.put(l.get(i), Integer.valueOf(i)); + } + return m; + + } + +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReflectiveStatementInterceptorAdapter.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReflectiveStatementInterceptorAdapter.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReflectiveStatementInterceptorAdapter.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,104 @@ +/* + Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.util.Properties; + +public class ReflectiveStatementInterceptorAdapter implements + StatementInterceptorV2 { + + private final StatementInterceptor toProxy; + + final Method v2PostProcessMethod; + + public ReflectiveStatementInterceptorAdapter(StatementInterceptor toProxy) { + this.toProxy = toProxy; + this.v2PostProcessMethod = getV2PostProcessMethod(toProxy.getClass()); + } + + public void destroy() { + toProxy.destroy(); + } + + public boolean executeTopLevelOnly() { + return toProxy.executeTopLevelOnly(); + } + + public void init(Connection conn, Properties props) throws SQLException { + toProxy.init(conn, props); + } + + public ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection, + int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, + SQLException statementException) throws SQLException { + // TODO Auto-generated method stub + try { + return (ResultSetInternalMethods) v2PostProcessMethod.invoke(toProxy, new Object[] {sql, + interceptedStatement, + originalResultSet, connection, + Integer.valueOf(warningCount), noIndexUsed ? Boolean.TRUE : Boolean.FALSE, noGoodIndexUsed ? Boolean.TRUE: Boolean.FALSE, + statementException}); + } catch (IllegalArgumentException e) { + SQLException sqlEx = new SQLException("Unable to reflectively invoke interceptor"); + sqlEx.initCause(e); + + throw sqlEx; + } catch (IllegalAccessException e) { + SQLException sqlEx = new SQLException("Unable to reflectively invoke interceptor"); + sqlEx.initCause(e); + + throw sqlEx; + } catch (InvocationTargetException e) { + SQLException sqlEx = new SQLException("Unable to reflectively invoke interceptor"); + sqlEx.initCause(e); + + throw sqlEx; + } + } + + public ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException { + return toProxy.preProcess(sql, interceptedStatement, connection); + } + + public static final Method getV2PostProcessMethod(Class toProxyClass) { + try { + Method postProcessMethod = toProxyClass.getMethod("postProcess", new Class[] { + String.class, Statement.class, ResultSetInternalMethods.class, Connection.class, Integer.TYPE, + Boolean.TYPE, Boolean.TYPE, SQLException.class}); + + return postProcessMethod; + } catch (SecurityException e) { + return null; + } catch (NoSuchMethodException e) { + return null; + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnection.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnection.java (.../ReplicationConnection.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnection.java (.../ReplicationConnection.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,24 +1,26 @@ /* - Copyright (C) 2004 MySQL AB + Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ + package com.mysql.jdbc; import java.sql.CallableStatement; @@ -28,9 +30,15 @@ import java.sql.SQLWarning; import java.sql.Savepoint; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.TimeZone; +import java.util.concurrent.Executor; +import com.mysql.jdbc.log.Log; + /** * Connection that opens two connections, one two a replication master, and * another to one or more slaves, and decides to use master when the connection @@ -39,43 +47,177 @@ * @version $Id: ReplicationConnection.java,v 1.1.2.1 2005/05/13 18:58:38 * mmatthews Exp $ */ -public class ReplicationConnection implements java.sql.Connection, PingTarget { - private Connection currentConnection; +public class ReplicationConnection implements Connection, PingTarget { + protected Connection currentConnection; - private Connection masterConnection; + protected LoadBalancedConnection masterConnection; - private Connection slavesConnection; + protected LoadBalancedConnection slavesConnection; + + private Properties slaveProperties; + + private Properties masterProperties; + + private NonRegisteringDriver driver; + private long connectionGroupID = -1; + + private ReplicationConnectionGroup connectionGroup; + + private List slaveHosts; + + private List masterHosts; + + private boolean allowMasterDownConnections = false; + + private boolean enableJMX = false; + + private boolean readOnly = false; + + protected ReplicationConnection() {} + public ReplicationConnection(Properties masterProperties, - Properties slaveProperties) throws SQLException { - Driver driver = new Driver(); + Properties slaveProperties, List masterHostList, List slaveHostList) throws SQLException { + String enableJMXAsString = masterProperties.getProperty("replicationEnableJMX", + "false"); + try{ + enableJMX = Boolean.parseBoolean(enableJMXAsString); + } catch (Exception e){ + throw SQLError.createSQLException(Messages.getString( + "ReplicationConnection.badValueForReplicationEnableJMX", + new Object[] { enableJMXAsString }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } + + String allowMasterDownConnectionsAsString = masterProperties.getProperty("allowMasterDownConnections", + "false"); + try{ + this.allowMasterDownConnections = Boolean.parseBoolean(allowMasterDownConnectionsAsString); + } catch (Exception e){ + throw SQLError.createSQLException(Messages.getString( + "ReplicationConnection.badValueForAllowMasterDownConnections", + new Object[] { enableJMXAsString }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + } - StringBuffer masterUrl = new StringBuffer("jdbc:mysql://"); - StringBuffer slaveUrl = new StringBuffer("jdbc:mysql://"); + + String group = masterProperties.getProperty("replicationConnectionGroup", + null); + + if(group != null){ + this.connectionGroup = ReplicationConnectionGroupManager.getConnectionGroupInstance(group); + if(enableJMX){ + ReplicationConnectionGroupManager.registerJmx(); + } + this.connectionGroupID = this.connectionGroup.registerReplicationConnection(this, masterHostList, slaveHostList); + + this.slaveHosts = new ArrayList(this.connectionGroup.getSlaveHosts()); + this.masterHosts = new ArrayList(this.connectionGroup.getMasterHosts()); + } else { + this.slaveHosts = new ArrayList(slaveHostList); + this.masterHosts = new ArrayList(masterHostList); + } - String masterHost = masterProperties - .getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY); - - if (masterHost != null) { - masterUrl.append(masterHost); + this.driver = new NonRegisteringDriver(); + this.slaveProperties = slaveProperties; + this.masterProperties = masterProperties; + + boolean createdMaster = this.initializeMasterConnection(); + this.initializeSlaveConnection(); + if(!createdMaster) { + this.readOnly = true; + this.currentConnection = this.slavesConnection; + return; } - - String slaveHost = slaveProperties - .getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY); - - if (slaveHost != null) { - slaveUrl.append(slaveHost); - } + this.currentConnection = this.masterConnection; + } + + private boolean initializeMasterConnection() throws SQLException { + return this.initializeMasterConnection(this.allowMasterDownConnections); + } + + public long getConnectionGroupId() { + return this.connectionGroupID; + } + + private boolean initializeMasterConnection(boolean allowMasterDown) throws SQLException { + // get this value before we change the masterConnection reference: + boolean isMaster = this.isMasterConnection(); + + StringBuffer masterUrl = new StringBuffer(NonRegisteringDriver.LOADBALANCE_URL_PREFIX); + + + boolean firstHost = true; + for(String host : this.masterHosts) { + if(!firstHost) { + masterUrl.append(','); + } + masterUrl.append(host); + firstHost = false; + } + String masterDb = masterProperties .getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY); + masterUrl.append("/"); if (masterDb != null) { masterUrl.append(masterDb); } + LoadBalancedConnection newMasterConn = null; + try { + newMasterConn = (com.mysql.jdbc.LoadBalancedConnection) driver.connect( + masterUrl.toString(), masterProperties); + } catch (SQLException ex) { + if(allowMasterDown){ + this.currentConnection = this.slavesConnection; + this.masterConnection = null; + this.readOnly = true; + return false; + } + throw ex; + } + + + if(isMaster && this.currentConnection != null) { + this.swapConnections(newMasterConn, currentConnection); + } + + if(this.masterConnection != null) { + try { + this.masterConnection.close(); + this.masterConnection = null; + } catch (SQLException e) {} + } + + + this.masterConnection = newMasterConn; + return true; + + + } + + + private void initializeSlaveConnection() throws SQLException { + if (this.slaveHosts.size() == 0) { + return; + } + + StringBuffer slaveUrl = new StringBuffer(NonRegisteringDriver.LOADBALANCE_URL_PREFIX); + + boolean firstHost = true; + for(String host : this.slaveHosts) { + if(!firstHost) { + slaveUrl.append(','); + } + slaveUrl.append(host); + firstHost = false; + } + + String slaveDb = slaveProperties .getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY); @@ -85,21 +227,28 @@ slaveUrl.append(slaveDb); } - this.masterConnection = (com.mysql.jdbc.Connection) driver.connect( - masterUrl.toString(), masterProperties); - this.slavesConnection = (com.mysql.jdbc.Connection) driver.connect( + + this.slavesConnection = (com.mysql.jdbc.LoadBalancedConnection) driver.connect( slaveUrl.toString(), slaveProperties); - - this.currentConnection = this.masterConnection; + this.slavesConnection.setReadOnly(true); + + // switch to slaves connection if we're in read-only mode and + // currently on the master. this means we didn't have any + // slaves to use until now + if (this.currentConnection != null && + this.currentConnection == this.masterConnection && + this.readOnly) { + switchToSlavesConnection(); + } } /* * (non-Javadoc) * * @see java.sql.Connection#clearWarnings() */ - public synchronized void clearWarnings() throws SQLException { - this.currentConnection.clearWarnings(); + public void clearWarnings() throws SQLException { + getCurrentConnection().clearWarnings(); } /* @@ -108,26 +257,145 @@ * @see java.sql.Connection#close() */ public synchronized void close() throws SQLException { - this.masterConnection.close(); - this.slavesConnection.close(); + if(this.masterConnection != null) { + this.masterConnection.close(); + } + if(this.slavesConnection != null) { + this.slavesConnection.close(); + } + + if (this.connectionGroup != null) { + this.connectionGroup.handleCloseConnection(this); + } + } /* * (non-Javadoc) * * @see java.sql.Connection#commit() */ - public synchronized void commit() throws SQLException { - this.currentConnection.commit(); + public void commit() throws SQLException { + getCurrentConnection().commit(); } + + public boolean isHostMaster(String host) { + if(host == null) { + return false; + } + for(String test : this.masterHosts) { + if(test.equalsIgnoreCase(host)) { + return true; + } + } + return false; + } + + public boolean isHostSlave(String host) { + if(host == null) { + return false; + } + for(String test : this.slaveHosts) { + if(test.equalsIgnoreCase(host)) { + return true; + } + } + return false; + + + } + + + + public synchronized void removeSlave(String host) throws SQLException { + removeSlave(host, true); + } + + public synchronized void removeSlave(String host, boolean closeGently) throws SQLException { + + this.slaveHosts.remove(host); + if(this.slavesConnection == null) { + return; + } + + if(closeGently) { + slavesConnection.removeHostWhenNotInUse(host); + } else { + slavesConnection.removeHost(host); + } + + // close the connection if it's the last slave + if (this.slaveHosts.size() == 0) { + switchToMasterConnection(); + this.slavesConnection.close(); + this.slavesConnection = null; + setReadOnly(this.readOnly); // maintain + } + } + + public synchronized void addSlaveHost(String host) throws SQLException { + if(this.isHostSlave(host)){ + // throw new SQLException("Cannot add existing host!"); + return; + } + this.slaveHosts.add(host); + if (this.slavesConnection == null) { + initializeSlaveConnection(); + } else { + this.slavesConnection.addHost(host); + } + } + + public synchronized void promoteSlaveToMaster(String host) throws SQLException { + if(!this.isHostSlave(host)) { +// turned this off as one might walk up the replication tree and set master +// to the current's master's master. +// throw SQLError.createSQLException("Cannot promote host " + host + " to master, as it must first be configured as a slave.", null); + + } + + this.masterHosts.add(host); + this.removeSlave(host); + if(this.masterConnection != null) { + this.masterConnection.addHost(host); + } + + } + + public synchronized void removeMasterHost(String host) throws SQLException { + this.removeMasterHost(host, true); + } + + public synchronized void removeMasterHost(String host, boolean waitUntilNotInUse) throws SQLException { + this.removeMasterHost(host, waitUntilNotInUse, false); + } + + public synchronized void removeMasterHost(String host, boolean waitUntilNotInUse, boolean isNowSlave) throws SQLException { + if(isNowSlave) { + this.slaveHosts.add(host); + } + this.masterHosts.remove(host); + + if(this.masterConnection == null) { + return; + } + + if(waitUntilNotInUse){ + this.masterConnection.removeHostWhenNotInUse(host); + } else { + this.masterConnection.removeHost(host); + } + + } + /* * (non-Javadoc) * * @see java.sql.Connection#createStatement() */ public Statement createStatement() throws SQLException { - Statement stmt = this.currentConnection.createStatement(); + Statement stmt = getCurrentConnection().createStatement(); ((com.mysql.jdbc.Statement) stmt).setPingTarget(this); return stmt; @@ -138,9 +406,9 @@ * * @see java.sql.Connection#createStatement(int, int) */ - public synchronized Statement createStatement(int resultSetType, + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - Statement stmt = this.currentConnection.createStatement(resultSetType, + Statement stmt = getCurrentConnection().createStatement(resultSetType, resultSetConcurrency); ((com.mysql.jdbc.Statement) stmt).setPingTarget(this); @@ -153,10 +421,10 @@ * * @see java.sql.Connection#createStatement(int, int, int) */ - public synchronized Statement createStatement(int resultSetType, + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - Statement stmt = this.currentConnection.createStatement(resultSetType, + Statement stmt = getCurrentConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); ((com.mysql.jdbc.Statement) stmt).setPingTarget(this); @@ -169,17 +437,17 @@ * * @see java.sql.Connection#getAutoCommit() */ - public synchronized boolean getAutoCommit() throws SQLException { - return this.currentConnection.getAutoCommit(); + public boolean getAutoCommit() throws SQLException { + return getCurrentConnection().getAutoCommit(); } /* * (non-Javadoc) * * @see java.sql.Connection#getCatalog() */ - public synchronized String getCatalog() throws SQLException { - return this.currentConnection.getCatalog(); + public String getCatalog() throws SQLException { + return getCurrentConnection().getCatalog(); } public synchronized Connection getCurrentConnection() { @@ -191,8 +459,8 @@ * * @see java.sql.Connection#getHoldability() */ - public synchronized int getHoldability() throws SQLException { - return this.currentConnection.getHoldability(); + public int getHoldability() throws SQLException { + return getCurrentConnection().getHoldability(); } public synchronized Connection getMasterConnection() { @@ -204,8 +472,8 @@ * * @see java.sql.Connection#getMetaData() */ - public synchronized DatabaseMetaData getMetaData() throws SQLException { - return this.currentConnection.getMetaData(); + public DatabaseMetaData getMetaData() throws SQLException { + return getCurrentConnection().getMetaData(); } public synchronized Connection getSlavesConnection() { @@ -217,35 +485,35 @@ * * @see java.sql.Connection#getTransactionIsolation() */ - public synchronized int getTransactionIsolation() throws SQLException { - return this.currentConnection.getTransactionIsolation(); + public int getTransactionIsolation() throws SQLException { + return getCurrentConnection().getTransactionIsolation(); } /* * (non-Javadoc) * * @see java.sql.Connection#getTypeMap() */ - public synchronized Map getTypeMap() throws SQLException { - return this.currentConnection.getTypeMap(); + public Map> getTypeMap() throws SQLException { + return getCurrentConnection().getTypeMap(); } /* * (non-Javadoc) * * @see java.sql.Connection#getWarnings() */ - public synchronized SQLWarning getWarnings() throws SQLException { - return this.currentConnection.getWarnings(); + public SQLWarning getWarnings() throws SQLException { + return getCurrentConnection().getWarnings(); } /* * (non-Javadoc) * * @see java.sql.Connection#isClosed() */ - public synchronized boolean isClosed() throws SQLException { - return this.currentConnection.isClosed(); + public boolean isClosed() throws SQLException { + return getCurrentConnection().isClosed(); } /* @@ -254,16 +522,16 @@ * @see java.sql.Connection#isReadOnly() */ public synchronized boolean isReadOnly() throws SQLException { - return this.currentConnection == this.slavesConnection; + return this.readOnly; } /* * (non-Javadoc) * * @see java.sql.Connection#nativeSQL(java.lang.String) */ - public synchronized String nativeSQL(String sql) throws SQLException { - return this.currentConnection.nativeSQL(sql); + public String nativeSQL(String sql) throws SQLException { + return getCurrentConnection().nativeSQL(sql); } /* @@ -272,17 +540,17 @@ * @see java.sql.Connection#prepareCall(java.lang.String) */ public CallableStatement prepareCall(String sql) throws SQLException { - return this.currentConnection.prepareCall(sql); + return getCurrentConnection().prepareCall(sql); } /* * (non-Javadoc) * * @see java.sql.Connection#prepareCall(java.lang.String, int, int) */ - public synchronized CallableStatement prepareCall(String sql, + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return this.currentConnection.prepareCall(sql, resultSetType, + return getCurrentConnection().prepareCall(sql, resultSetType, resultSetConcurrency); } @@ -291,10 +559,10 @@ * * @see java.sql.Connection#prepareCall(java.lang.String, int, int, int) */ - public synchronized CallableStatement prepareCall(String sql, + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return this.currentConnection.prepareCall(sql, resultSetType, + return getCurrentConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } @@ -304,8 +572,8 @@ * @see java.sql.Connection#prepareStatement(java.lang.String) */ public PreparedStatement prepareStatement(String sql) throws SQLException { - PreparedStatement pstmt = this.currentConnection.prepareStatement(sql); - + PreparedStatement pstmt = getCurrentConnection().prepareStatement(sql); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); return pstmt; @@ -316,9 +584,9 @@ * * @see java.sql.Connection#prepareStatement(java.lang.String, int) */ - public synchronized PreparedStatement prepareStatement(String sql, + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - PreparedStatement pstmt = this.currentConnection.prepareStatement(sql, autoGeneratedKeys); + PreparedStatement pstmt = getCurrentConnection().prepareStatement(sql, autoGeneratedKeys); ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); @@ -330,9 +598,9 @@ * * @see java.sql.Connection#prepareStatement(java.lang.String, int, int) */ - public synchronized PreparedStatement prepareStatement(String sql, + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - PreparedStatement pstmt = this.currentConnection.prepareStatement(sql, resultSetType, + PreparedStatement pstmt = getCurrentConnection().prepareStatement(sql, resultSetType, resultSetConcurrency); ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); @@ -346,10 +614,10 @@ * @see java.sql.Connection#prepareStatement(java.lang.String, int, int, * int) */ - public synchronized PreparedStatement prepareStatement(String sql, + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - PreparedStatement pstmt = this.currentConnection.prepareStatement(sql, resultSetType, + PreparedStatement pstmt = getCurrentConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); @@ -362,9 +630,9 @@ * * @see java.sql.Connection#prepareStatement(java.lang.String, int[]) */ - public synchronized PreparedStatement prepareStatement(String sql, + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - PreparedStatement pstmt = this.currentConnection.prepareStatement(sql, columnIndexes); + PreparedStatement pstmt = getCurrentConnection().prepareStatement(sql, columnIndexes); ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); @@ -377,9 +645,9 @@ * @see java.sql.Connection#prepareStatement(java.lang.String, * java.lang.String[]) */ - public synchronized PreparedStatement prepareStatement(String sql, + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - PreparedStatement pstmt = this.currentConnection.prepareStatement(sql, columnNames); + PreparedStatement pstmt = getCurrentConnection().prepareStatement(sql, columnNames); ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); @@ -391,56 +659,56 @@ * * @see java.sql.Connection#releaseSavepoint(java.sql.Savepoint) */ - public synchronized void releaseSavepoint(Savepoint savepoint) + public void releaseSavepoint(Savepoint savepoint) throws SQLException { - this.currentConnection.releaseSavepoint(savepoint); + getCurrentConnection().releaseSavepoint(savepoint); } /* * (non-Javadoc) * * @see java.sql.Connection#rollback() */ - public synchronized void rollback() throws SQLException { - this.currentConnection.rollback(); + public void rollback() throws SQLException { + getCurrentConnection().rollback(); } /* * (non-Javadoc) * * @see java.sql.Connection#rollback(java.sql.Savepoint) */ - public synchronized void rollback(Savepoint savepoint) throws SQLException { - this.currentConnection.rollback(savepoint); + public void rollback(Savepoint savepoint) throws SQLException { + getCurrentConnection().rollback(savepoint); } /* * (non-Javadoc) * * @see java.sql.Connection#setAutoCommit(boolean) */ - public synchronized void setAutoCommit(boolean autoCommit) + public void setAutoCommit(boolean autoCommit) throws SQLException { - this.currentConnection.setAutoCommit(autoCommit); + getCurrentConnection().setAutoCommit(autoCommit); } /* * (non-Javadoc) * * @see java.sql.Connection#setCatalog(java.lang.String) */ - public synchronized void setCatalog(String catalog) throws SQLException { - this.currentConnection.setCatalog(catalog); + public void setCatalog(String catalog) throws SQLException { + getCurrentConnection().setCatalog(catalog); } /* * (non-Javadoc) * * @see java.sql.Connection#setHoldability(int) */ - public synchronized void setHoldability(int holdability) + public void setHoldability(int holdability) throws SQLException { - this.currentConnection.setHoldability(holdability); + getCurrentConnection().setHoldability(holdability); } /* @@ -458,53 +726,60 @@ switchToMasterConnection(); } } + this.readOnly = readOnly; + // allow master connection to be set to/from read-only if + // there are no slaves + if (this.currentConnection == this.masterConnection) { + this.currentConnection.setReadOnly(this.readOnly); + } } /* * (non-Javadoc) * * @see java.sql.Connection#setSavepoint() */ - public synchronized Savepoint setSavepoint() throws SQLException { - return this.currentConnection.setSavepoint(); + public Savepoint setSavepoint() throws SQLException { + return getCurrentConnection().setSavepoint(); } /* * (non-Javadoc) * * @see java.sql.Connection#setSavepoint(java.lang.String) */ - public synchronized Savepoint setSavepoint(String name) throws SQLException { - return this.currentConnection.setSavepoint(name); + public Savepoint setSavepoint(String name) throws SQLException { + return getCurrentConnection().setSavepoint(name); } /* * (non-Javadoc) * * @see java.sql.Connection#setTransactionIsolation(int) */ - public synchronized void setTransactionIsolation(int level) + public void setTransactionIsolation(int level) throws SQLException { - this.currentConnection.setTransactionIsolation(level); + getCurrentConnection().setTransactionIsolation(level); } // For testing - /* - * (non-Javadoc) - * - * @see java.sql.Connection#setTypeMap(java.util.Map) - */ - public synchronized void setTypeMap(Map arg0) throws SQLException { - this.currentConnection.setTypeMap(arg0); - } - private synchronized void switchToMasterConnection() throws SQLException { + if(this.masterConnection == null || this.masterConnection.isClosed()){ + this.initializeMasterConnection(); + } swapConnections(this.masterConnection, this.slavesConnection); + this.masterConnection.setReadOnly(false); } private synchronized void switchToSlavesConnection() throws SQLException { - swapConnections(this.slavesConnection, this.masterConnection); + if(this.slavesConnection == null || this.slavesConnection.isClosed()) { + this.initializeSlaveConnection(); + } + if (this.slavesConnection != null) { + swapConnections(this.slavesConnection, this.masterConnection); + this.slavesConnection.setReadOnly(true); + } } /** @@ -519,6 +794,7 @@ */ private synchronized void swapConnections(Connection switchToConnection, Connection switchFromConnection) throws SQLException { + String switchFromCatalog = switchFromConnection.getCatalog(); String switchToCatalog = switchToConnection.getCatalog(); @@ -545,16 +821,2203 @@ .setTransactionIsolation(switchFromIsolation); } + switchToConnection.setSessionMaxRows(switchFromConnection.getSessionMaxRows()); + this.currentConnection = switchToConnection; } public synchronized void doPing() throws SQLException { + boolean isMasterConn = this.isMasterConnection(); if (this.masterConnection != null) { - this.masterConnection.ping(); + try { + this.masterConnection.ping(); + } catch (SQLException e) { + if (isMasterConn) { + // flip to slave connections: + this.currentConnection = this.slavesConnection; + this.masterConnection = null; + + throw e; + } + } + } else { + this.initializeMasterConnection(); } if (this.slavesConnection != null) { + try { + this.slavesConnection.ping(); + } catch (SQLException e) { + if (!isMasterConn) { + // flip to master connection: + this.currentConnection = this.masterConnection; + this.slavesConnection = null; + + throw e; + } + } + } else { + this.initializeSlaveConnection(); + } + } + + public synchronized void changeUser(String userName, String newPassword) + throws SQLException { + this.masterConnection.changeUser(userName, newPassword); + this.slavesConnection.changeUser(userName, newPassword); + } + + public synchronized void clearHasTriedMaster() { + this.masterConnection.clearHasTriedMaster(); + this.slavesConnection.clearHasTriedMaster(); + + } + + public PreparedStatement clientPrepareStatement(String sql) + throws SQLException { + PreparedStatement pstmt = getCurrentConnection().clientPrepareStatement(sql); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement clientPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().clientPrepareStatement(sql, autoGenKeyIndex); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().clientPrepareStatement(sql, resultSetType, resultSetConcurrency); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement clientPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().clientPrepareStatement(sql, autoGenKeyIndexes); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().clientPrepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement clientPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().clientPrepareStatement(sql, autoGenKeyColNames); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public int getActiveStatementCount() { + return getCurrentConnection().getActiveStatementCount(); + } + + public long getIdleFor() { + return getCurrentConnection().getIdleFor(); + } + + public Log getLog() throws SQLException { + return getCurrentConnection().getLog(); + } + + public String getServerCharacterEncoding() { + return getCurrentConnection().getServerCharacterEncoding(); + } + + public TimeZone getServerTimezoneTZ() { + return getCurrentConnection().getServerTimezoneTZ(); + } + + public String getStatementComment() { + return getCurrentConnection().getStatementComment(); + } + + public boolean hasTriedMaster() { + return getCurrentConnection().hasTriedMaster(); + } + + public void initializeExtension(Extension ex) throws SQLException { + getCurrentConnection().initializeExtension(ex); + } + + public boolean isAbonormallyLongQuery(long millisOrNanos) { + return getCurrentConnection().isAbonormallyLongQuery(millisOrNanos); + } + + public boolean isInGlobalTx() { + return getCurrentConnection().isInGlobalTx(); + } + + public boolean isMasterConnection() { + if(this.currentConnection == null) { + return true; + } + return this.currentConnection == this.masterConnection; + } + + public boolean isNoBackslashEscapesSet() { + return getCurrentConnection().isNoBackslashEscapesSet(); + } + + public boolean lowerCaseTableNames() { + return getCurrentConnection().lowerCaseTableNames(); + } + + public boolean parserKnowsUnicode() { + return getCurrentConnection().parserKnowsUnicode(); + } + + public synchronized void ping() throws SQLException { + try { + this.masterConnection.ping(); + } catch (SQLException e) { + if (this.isMasterConnection()) { + throw e; + } + } + try { this.slavesConnection.ping(); + } catch (SQLException e) { + if (!this.isMasterConnection()) { + throw e; + } } } -} \ No newline at end of file + + public void reportQueryTime(long millisOrNanos) { + getCurrentConnection().reportQueryTime(millisOrNanos); + } + + public void resetServerState() throws SQLException { + getCurrentConnection().resetServerState(); + } + + public PreparedStatement serverPrepareStatement(String sql) + throws SQLException { + PreparedStatement pstmt = getCurrentConnection().serverPrepareStatement(sql); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement serverPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().serverPrepareStatement(sql, autoGenKeyIndex); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().serverPrepareStatement(sql, resultSetType, resultSetConcurrency); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().serverPrepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement serverPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().serverPrepareStatement(sql, autoGenKeyIndexes); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public PreparedStatement serverPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + PreparedStatement pstmt = getCurrentConnection().serverPrepareStatement(sql, autoGenKeyColNames); + ((com.mysql.jdbc.Statement) pstmt).setPingTarget(this); + + return pstmt; + } + + public void setFailedOver(boolean flag) { + getCurrentConnection().setFailedOver(flag); + } + + public void setPreferSlaveDuringFailover(boolean flag) { + getCurrentConnection().setPreferSlaveDuringFailover(flag); + } + + public synchronized void setStatementComment(String comment) { + this.masterConnection.setStatementComment(comment); + this.slavesConnection.setStatementComment(comment); + } + + public void shutdownServer() throws SQLException { + getCurrentConnection().shutdownServer(); + } + + public boolean supportsIsolationLevel() { + return getCurrentConnection().supportsIsolationLevel(); + } + + public boolean supportsQuotedIdentifiers() { + return getCurrentConnection().supportsQuotedIdentifiers(); + } + + public boolean supportsTransactions() { + return getCurrentConnection().supportsTransactions(); + } + + public boolean versionMeetsMinimum(int major, int minor, int subminor) + throws SQLException { + return getCurrentConnection().versionMeetsMinimum(major, minor, subminor); + } + + public String exposeAsXml() throws SQLException { + return getCurrentConnection().exposeAsXml(); + } + + public boolean getAllowLoadLocalInfile() { + return getCurrentConnection().getAllowLoadLocalInfile(); + } + + public boolean getAllowMultiQueries() { + return getCurrentConnection().getAllowMultiQueries(); + } + + public boolean getAllowNanAndInf() { + return getCurrentConnection().getAllowNanAndInf(); + } + + public boolean getAllowUrlInLocalInfile() { + return getCurrentConnection().getAllowUrlInLocalInfile(); + } + + public boolean getAlwaysSendSetIsolation() { + return getCurrentConnection().getAlwaysSendSetIsolation(); + } + + public boolean getAutoClosePStmtStreams() { + return getCurrentConnection().getAutoClosePStmtStreams(); + } + + public boolean getAutoDeserialize() { + return getCurrentConnection().getAutoDeserialize(); + } + + public boolean getAutoGenerateTestcaseScript() { + return getCurrentConnection().getAutoGenerateTestcaseScript(); + } + + public boolean getAutoReconnectForPools() { + return getCurrentConnection().getAutoReconnectForPools(); + } + + public boolean getAutoSlowLog() { + return getCurrentConnection().getAutoSlowLog(); + } + + public int getBlobSendChunkSize() { + return getCurrentConnection().getBlobSendChunkSize(); + } + + public boolean getBlobsAreStrings() { + return getCurrentConnection().getBlobsAreStrings(); + } + + public boolean getCacheCallableStatements() { + return getCurrentConnection().getCacheCallableStatements(); + } + + public boolean getCacheCallableStmts() { + return getCurrentConnection().getCacheCallableStmts(); + } + + public boolean getCachePrepStmts() { + return getCurrentConnection().getCachePrepStmts(); + } + + public boolean getCachePreparedStatements() { + return getCurrentConnection().getCachePreparedStatements(); + } + + public boolean getCacheResultSetMetadata() { + return getCurrentConnection().getCacheResultSetMetadata(); + } + + public boolean getCacheServerConfiguration() { + return getCurrentConnection().getCacheServerConfiguration(); + } + + public int getCallableStatementCacheSize() { + return getCurrentConnection().getCallableStatementCacheSize(); + } + + public int getCallableStmtCacheSize() { + return getCurrentConnection().getCallableStmtCacheSize(); + } + + public boolean getCapitalizeTypeNames() { + return getCurrentConnection().getCapitalizeTypeNames(); + } + + public String getCharacterSetResults() { + return getCurrentConnection().getCharacterSetResults(); + } + + public String getClientCertificateKeyStorePassword() { + return getCurrentConnection().getClientCertificateKeyStorePassword(); + } + + public String getClientCertificateKeyStoreType() { + return getCurrentConnection().getClientCertificateKeyStoreType(); + } + + public String getClientCertificateKeyStoreUrl() { + return getCurrentConnection().getClientCertificateKeyStoreUrl(); + } + + public String getClientInfoProvider() { + return getCurrentConnection().getClientInfoProvider(); + } + + public String getClobCharacterEncoding() { + return getCurrentConnection().getClobCharacterEncoding(); + } + + public boolean getClobberStreamingResults() { + return getCurrentConnection().getClobberStreamingResults(); + } + + public int getConnectTimeout() { + return getCurrentConnection().getConnectTimeout(); + } + + public String getConnectionCollation() { + return getCurrentConnection().getConnectionCollation(); + } + + public String getConnectionLifecycleInterceptors() { + return getCurrentConnection().getConnectionLifecycleInterceptors(); + } + + public boolean getContinueBatchOnError() { + return getCurrentConnection().getContinueBatchOnError(); + } + + public boolean getCreateDatabaseIfNotExist() { + return getCurrentConnection().getCreateDatabaseIfNotExist(); + } + + public int getDefaultFetchSize() { + return getCurrentConnection().getDefaultFetchSize(); + } + + public boolean getDontTrackOpenResources() { + return getCurrentConnection().getDontTrackOpenResources(); + } + + public boolean getDumpMetadataOnColumnNotFound() { + return getCurrentConnection().getDumpMetadataOnColumnNotFound(); + } + + public boolean getDumpQueriesOnException() { + return getCurrentConnection().getDumpQueriesOnException(); + } + + public boolean getDynamicCalendars() { + return getCurrentConnection().getDynamicCalendars(); + } + + public boolean getElideSetAutoCommits() { + return getCurrentConnection().getElideSetAutoCommits(); + } + + public boolean getEmptyStringsConvertToZero() { + return getCurrentConnection().getEmptyStringsConvertToZero(); + } + + public boolean getEmulateLocators() { + return getCurrentConnection().getEmulateLocators(); + } + + public boolean getEmulateUnsupportedPstmts() { + return getCurrentConnection().getEmulateUnsupportedPstmts(); + } + + public boolean getEnablePacketDebug() { + return getCurrentConnection().getEnablePacketDebug(); + } + + public boolean getEnableQueryTimeouts() { + return getCurrentConnection().getEnableQueryTimeouts(); + } + + public String getEncoding() { + return getCurrentConnection().getEncoding(); + } + + public boolean getExplainSlowQueries() { + return getCurrentConnection().getExplainSlowQueries(); + } + + public boolean getFailOverReadOnly() { + return getCurrentConnection().getFailOverReadOnly(); + } + + public boolean getFunctionsNeverReturnBlobs() { + return getCurrentConnection().getFunctionsNeverReturnBlobs(); + } + + public boolean getGatherPerfMetrics() { + return getCurrentConnection().getGatherPerfMetrics(); + } + + public boolean getGatherPerformanceMetrics() { + return getCurrentConnection().getGatherPerformanceMetrics(); + } + + public boolean getGenerateSimpleParameterMetadata() { + return getCurrentConnection().getGenerateSimpleParameterMetadata(); + } + + public boolean getHoldResultsOpenOverStatementClose() { + return getCurrentConnection().getHoldResultsOpenOverStatementClose(); + } + + public boolean getIgnoreNonTxTables() { + return getCurrentConnection().getIgnoreNonTxTables(); + } + + public boolean getIncludeInnodbStatusInDeadlockExceptions() { + return getCurrentConnection().getIncludeInnodbStatusInDeadlockExceptions(); + } + + public int getInitialTimeout() { + return getCurrentConnection().getInitialTimeout(); + } + + public boolean getInteractiveClient() { + return getCurrentConnection().getInteractiveClient(); + } + + public boolean getIsInteractiveClient() { + return getCurrentConnection().getIsInteractiveClient(); + } + + public boolean getJdbcCompliantTruncation() { + return getCurrentConnection().getJdbcCompliantTruncation(); + } + + public boolean getJdbcCompliantTruncationForReads() { + return getCurrentConnection().getJdbcCompliantTruncationForReads(); + } + + public String getLargeRowSizeThreshold() { + return getCurrentConnection().getLargeRowSizeThreshold(); + } + + public String getLoadBalanceStrategy() { + return getCurrentConnection().getLoadBalanceStrategy(); + } + + public String getLocalSocketAddress() { + return getCurrentConnection().getLocalSocketAddress(); + } + + public int getLocatorFetchBufferSize() { + return getCurrentConnection().getLocatorFetchBufferSize(); + } + + public boolean getLogSlowQueries() { + return getCurrentConnection().getLogSlowQueries(); + } + + public boolean getLogXaCommands() { + return getCurrentConnection().getLogXaCommands(); + } + + public String getLogger() { + return getCurrentConnection().getLogger(); + } + + public String getLoggerClassName() { + return getCurrentConnection().getLoggerClassName(); + } + + public boolean getMaintainTimeStats() { + return getCurrentConnection().getMaintainTimeStats(); + } + + public int getMaxQuerySizeToLog() { + return getCurrentConnection().getMaxQuerySizeToLog(); + } + + public int getMaxReconnects() { + return getCurrentConnection().getMaxReconnects(); + } + + public int getMaxRows() { + return getCurrentConnection().getMaxRows(); + } + + public int getMetadataCacheSize() { + return getCurrentConnection().getMetadataCacheSize(); + } + + public int getNetTimeoutForStreamingResults() { + return getCurrentConnection().getNetTimeoutForStreamingResults(); + } + + public boolean getNoAccessToProcedureBodies() { + return getCurrentConnection().getNoAccessToProcedureBodies(); + } + + public boolean getNoDatetimeStringSync() { + return getCurrentConnection().getNoDatetimeStringSync(); + } + + public boolean getNoTimezoneConversionForTimeType() { + return getCurrentConnection().getNoTimezoneConversionForTimeType(); + } + + public boolean getNullCatalogMeansCurrent() { + return getCurrentConnection().getNullCatalogMeansCurrent(); + } + + public boolean getNullNamePatternMatchesAll() { + return getCurrentConnection().getNullNamePatternMatchesAll(); + } + + public boolean getOverrideSupportsIntegrityEnhancementFacility() { + return getCurrentConnection().getOverrideSupportsIntegrityEnhancementFacility(); + } + + public int getPacketDebugBufferSize() { + return getCurrentConnection().getPacketDebugBufferSize(); + } + + public boolean getPadCharsWithSpace() { + return getCurrentConnection().getPadCharsWithSpace(); + } + + public boolean getParanoid() { + return getCurrentConnection().getParanoid(); + } + + public boolean getPedantic() { + return getCurrentConnection().getPedantic(); + } + + public boolean getPinGlobalTxToPhysicalConnection() { + return getCurrentConnection().getPinGlobalTxToPhysicalConnection(); + } + + public boolean getPopulateInsertRowWithDefaultValues() { + return getCurrentConnection().getPopulateInsertRowWithDefaultValues(); + } + + public int getPrepStmtCacheSize() { + return getCurrentConnection().getPrepStmtCacheSize(); + } + + public int getPrepStmtCacheSqlLimit() { + return getCurrentConnection().getPrepStmtCacheSqlLimit(); + } + + public int getPreparedStatementCacheSize() { + return getCurrentConnection().getPreparedStatementCacheSize(); + } + + public int getPreparedStatementCacheSqlLimit() { + return getCurrentConnection().getPreparedStatementCacheSqlLimit(); + } + + public boolean getProcessEscapeCodesForPrepStmts() { + return getCurrentConnection().getProcessEscapeCodesForPrepStmts(); + } + + public boolean getProfileSQL() { + return getCurrentConnection().getProfileSQL(); + } + + public boolean getProfileSql() { + return getCurrentConnection().getProfileSql(); + } + + public String getProfilerEventHandler() { + return getCurrentConnection().getProfilerEventHandler(); + } + + public String getPropertiesTransform() { + return getCurrentConnection().getPropertiesTransform(); + } + + public int getQueriesBeforeRetryMaster() { + return getCurrentConnection().getQueriesBeforeRetryMaster(); + } + + public boolean getReconnectAtTxEnd() { + return getCurrentConnection().getReconnectAtTxEnd(); + } + + public boolean getRelaxAutoCommit() { + return getCurrentConnection().getRelaxAutoCommit(); + } + + public int getReportMetricsIntervalMillis() { + return getCurrentConnection().getReportMetricsIntervalMillis(); + } + + public boolean getRequireSSL() { + return getCurrentConnection().getRequireSSL(); + } + + public String getResourceId() { + return getCurrentConnection().getResourceId(); + } + + public int getResultSetSizeThreshold() { + return getCurrentConnection().getResultSetSizeThreshold(); + } + + public boolean getRewriteBatchedStatements() { + return getCurrentConnection().getRewriteBatchedStatements(); + } + + public boolean getRollbackOnPooledClose() { + return getCurrentConnection().getRollbackOnPooledClose(); + } + + public boolean getRoundRobinLoadBalance() { + return getCurrentConnection().getRoundRobinLoadBalance(); + } + + public boolean getRunningCTS13() { + return getCurrentConnection().getRunningCTS13(); + } + + public int getSecondsBeforeRetryMaster() { + return getCurrentConnection().getSecondsBeforeRetryMaster(); + } + + public int getSelfDestructOnPingMaxOperations() { + return getCurrentConnection().getSelfDestructOnPingMaxOperations(); + } + + public int getSelfDestructOnPingSecondsLifetime() { + return getCurrentConnection().getSelfDestructOnPingSecondsLifetime(); + } + + public String getServerTimezone() { + return getCurrentConnection().getServerTimezone(); + } + + public String getSessionVariables() { + return getCurrentConnection().getSessionVariables(); + } + + public int getSlowQueryThresholdMillis() { + return getCurrentConnection().getSlowQueryThresholdMillis(); + } + + public long getSlowQueryThresholdNanos() { + return getCurrentConnection().getSlowQueryThresholdNanos(); + } + + public String getSocketFactory() { + return getCurrentConnection().getSocketFactory(); + } + + public String getSocketFactoryClassName() { + return getCurrentConnection().getSocketFactoryClassName(); + } + + public int getSocketTimeout() { + return getCurrentConnection().getSocketTimeout(); + } + + public String getStatementInterceptors() { + return getCurrentConnection().getStatementInterceptors(); + } + + public boolean getStrictFloatingPoint() { + return getCurrentConnection().getStrictFloatingPoint(); + } + + public boolean getStrictUpdates() { + return getCurrentConnection().getStrictUpdates(); + } + + public boolean getTcpKeepAlive() { + return getCurrentConnection().getTcpKeepAlive(); + } + + public boolean getTcpNoDelay() { + return getCurrentConnection().getTcpNoDelay(); + } + + public int getTcpRcvBuf() { + return getCurrentConnection().getTcpRcvBuf(); + } + + public int getTcpSndBuf() { + return getCurrentConnection().getTcpSndBuf(); + } + + public int getTcpTrafficClass() { + return getCurrentConnection().getTcpTrafficClass(); + } + + public boolean getTinyInt1isBit() { + return getCurrentConnection().getTinyInt1isBit(); + } + + public boolean getTraceProtocol() { + return getCurrentConnection().getTraceProtocol(); + } + + public boolean getTransformedBitIsBoolean() { + return getCurrentConnection().getTransformedBitIsBoolean(); + } + + public boolean getTreatUtilDateAsTimestamp() { + return getCurrentConnection().getTreatUtilDateAsTimestamp(); + } + + public String getTrustCertificateKeyStorePassword() { + return getCurrentConnection().getTrustCertificateKeyStorePassword(); + } + + public String getTrustCertificateKeyStoreType() { + return getCurrentConnection().getTrustCertificateKeyStoreType(); + } + + public String getTrustCertificateKeyStoreUrl() { + return getCurrentConnection().getTrustCertificateKeyStoreUrl(); + } + + public boolean getUltraDevHack() { + return getCurrentConnection().getUltraDevHack(); + } + + public boolean getUseBlobToStoreUTF8OutsideBMP() { + return getCurrentConnection().getUseBlobToStoreUTF8OutsideBMP(); + } + + public boolean getUseCompression() { + return getCurrentConnection().getUseCompression(); + } + + public String getUseConfigs() { + return getCurrentConnection().getUseConfigs(); + } + + public boolean getUseCursorFetch() { + return getCurrentConnection().getUseCursorFetch(); + } + + public boolean getUseDirectRowUnpack() { + return getCurrentConnection().getUseDirectRowUnpack(); + } + + public boolean getUseDynamicCharsetInfo() { + return getCurrentConnection().getUseDynamicCharsetInfo(); + } + + public boolean getUseFastDateParsing() { + return getCurrentConnection().getUseFastDateParsing(); + } + + public boolean getUseFastIntParsing() { + return getCurrentConnection().getUseFastIntParsing(); + } + + public boolean getUseGmtMillisForDatetimes() { + return getCurrentConnection().getUseGmtMillisForDatetimes(); + } + + public boolean getUseHostsInPrivileges() { + return getCurrentConnection().getUseHostsInPrivileges(); + } + + public boolean getUseInformationSchema() { + return getCurrentConnection().getUseInformationSchema(); + } + + public boolean getUseJDBCCompliantTimezoneShift() { + return getCurrentConnection().getUseJDBCCompliantTimezoneShift(); + } + + public boolean getUseJvmCharsetConverters() { + return getCurrentConnection().getUseJvmCharsetConverters(); + } + + public boolean getUseLegacyDatetimeCode() { + return getCurrentConnection().getUseLegacyDatetimeCode(); + } + + public boolean getUseLocalSessionState() { + return getCurrentConnection().getUseLocalSessionState(); + } + + public boolean getUseNanosForElapsedTime() { + return getCurrentConnection().getUseNanosForElapsedTime(); + } + + public boolean getUseOldAliasMetadataBehavior() { + return getCurrentConnection().getUseOldAliasMetadataBehavior(); + } + + public boolean getUseOldUTF8Behavior() { + return getCurrentConnection().getUseOldUTF8Behavior(); + } + + public boolean getUseOnlyServerErrorMessages() { + return getCurrentConnection().getUseOnlyServerErrorMessages(); + } + + public boolean getUseReadAheadInput() { + return getCurrentConnection().getUseReadAheadInput(); + } + + public boolean getUseSSL() { + return getCurrentConnection().getUseSSL(); + } + + public boolean getUseSSPSCompatibleTimezoneShift() { + return getCurrentConnection().getUseSSPSCompatibleTimezoneShift(); + } + + public boolean getUseServerPrepStmts() { + return getCurrentConnection().getUseServerPrepStmts(); + } + + public boolean getUseServerPreparedStmts() { + return getCurrentConnection().getUseServerPreparedStmts(); + } + + public boolean getUseSqlStateCodes() { + return getCurrentConnection().getUseSqlStateCodes(); + } + + public boolean getUseStreamLengthsInPrepStmts() { + return getCurrentConnection().getUseStreamLengthsInPrepStmts(); + } + + public boolean getUseTimezone() { + return getCurrentConnection().getUseTimezone(); + } + + public boolean getUseUltraDevWorkAround() { + return getCurrentConnection().getUseUltraDevWorkAround(); + } + + public boolean getUseUnbufferedInput() { + return getCurrentConnection().getUseUnbufferedInput(); + } + + public boolean getUseUnicode() { + return getCurrentConnection().getUseUnicode(); + } + + public boolean getUseUsageAdvisor() { + return getCurrentConnection().getUseUsageAdvisor(); + } + + public String getUtf8OutsideBmpExcludedColumnNamePattern() { + return getCurrentConnection().getUtf8OutsideBmpExcludedColumnNamePattern(); + } + + public String getUtf8OutsideBmpIncludedColumnNamePattern() { + return getCurrentConnection().getUtf8OutsideBmpIncludedColumnNamePattern(); + } + + public boolean getVerifyServerCertificate() { + return getCurrentConnection().getVerifyServerCertificate(); + } + + public boolean getYearIsDateType() { + return getCurrentConnection().getYearIsDateType(); + } + + public String getZeroDateTimeBehavior() { + return getCurrentConnection().getZeroDateTimeBehavior(); + } + + public void setAllowLoadLocalInfile(boolean property) { + // not runtime configurable + + } + + public void setAllowMultiQueries(boolean property) { + // not runtime configurable + + } + + public void setAllowNanAndInf(boolean flag) { + // not runtime configurable + + } + + public void setAllowUrlInLocalInfile(boolean flag) { + // not runtime configurable + + } + + public void setAlwaysSendSetIsolation(boolean flag) { + // not runtime configurable + + } + + public void setAutoClosePStmtStreams(boolean flag) { + // not runtime configurable + + } + + public void setAutoDeserialize(boolean flag) { + // not runtime configurable + + } + + public void setAutoGenerateTestcaseScript(boolean flag) { + // not runtime configurable + + } + + public void setAutoReconnect(boolean flag) { + // not runtime configurable + + } + + public void setAutoReconnectForConnectionPools(boolean property) { + // not runtime configurable + + } + + public void setAutoReconnectForPools(boolean flag) { + // not runtime configurable + + } + + public void setAutoSlowLog(boolean flag) { + // not runtime configurable + + } + + public void setBlobSendChunkSize(String value) throws SQLException { + // not runtime configurable + + } + + public void setBlobsAreStrings(boolean flag) { + // not runtime configurable + + } + + public void setCacheCallableStatements(boolean flag) { + // not runtime configurable + + } + + public void setCacheCallableStmts(boolean flag) { + // not runtime configurable + + } + + public void setCachePrepStmts(boolean flag) { + // not runtime configurable + + } + + public void setCachePreparedStatements(boolean flag) { + // not runtime configurable + + } + + public void setCacheResultSetMetadata(boolean property) { + // not runtime configurable + + } + + public void setCacheServerConfiguration(boolean flag) { + // not runtime configurable + + } + + public void setCallableStatementCacheSize(int size) { + // not runtime configurable + + } + + public void setCallableStmtCacheSize(int cacheSize) { + // not runtime configurable + + } + + public void setCapitalizeDBMDTypes(boolean property) { + // not runtime configurable + + } + + public void setCapitalizeTypeNames(boolean flag) { + // not runtime configurable + + } + + public void setCharacterEncoding(String encoding) { + // not runtime configurable + + } + + public void setCharacterSetResults(String characterSet) { + // not runtime configurable + + } + + public void setClientCertificateKeyStorePassword(String value) { + // not runtime configurable + + } + + public void setClientCertificateKeyStoreType(String value) { + // not runtime configurable + + } + + public void setClientCertificateKeyStoreUrl(String value) { + // not runtime configurable + + } + + public void setClientInfoProvider(String classname) { + // not runtime configurable + + } + + public void setClobCharacterEncoding(String encoding) { + // not runtime configurable + + } + + public void setClobberStreamingResults(boolean flag) { + // not runtime configurable + + } + + public void setConnectTimeout(int timeoutMs) { + // not runtime configurable + + } + + public void setConnectionCollation(String collation) { + // not runtime configurable + + } + + public void setConnectionLifecycleInterceptors(String interceptors) { + // not runtime configurable + + } + + public void setContinueBatchOnError(boolean property) { + // not runtime configurable + + } + + public void setCreateDatabaseIfNotExist(boolean flag) { + // not runtime configurable + + } + + public void setDefaultFetchSize(int n) { + // not runtime configurable + + } + + public void setDetectServerPreparedStmts(boolean property) { + // not runtime configurable + + } + + public void setDontTrackOpenResources(boolean flag) { + // not runtime configurable + + } + + public void setDumpMetadataOnColumnNotFound(boolean flag) { + // not runtime configurable + + } + + public void setDumpQueriesOnException(boolean flag) { + // not runtime configurable + + } + + public void setDynamicCalendars(boolean flag) { + // not runtime configurable + + } + + public void setElideSetAutoCommits(boolean flag) { + // not runtime configurable + + } + + public void setEmptyStringsConvertToZero(boolean flag) { + // not runtime configurable + + } + + public void setEmulateLocators(boolean property) { + // not runtime configurable + + } + + public void setEmulateUnsupportedPstmts(boolean flag) { + // not runtime configurable + + } + + public void setEnablePacketDebug(boolean flag) { + // not runtime configurable + + } + + public void setEnableQueryTimeouts(boolean flag) { + // not runtime configurable + + } + + public void setEncoding(String property) { + // not runtime configurable + + } + + public void setExplainSlowQueries(boolean flag) { + // not runtime configurable + + } + + public void setFailOverReadOnly(boolean flag) { + // not runtime configurable + + } + + public void setFunctionsNeverReturnBlobs(boolean flag) { + // not runtime configurable + + } + + public void setGatherPerfMetrics(boolean flag) { + // not runtime configurable + + } + + public void setGatherPerformanceMetrics(boolean flag) { + // not runtime configurable + + } + + public void setGenerateSimpleParameterMetadata(boolean flag) { + // not runtime configurable + + } + + public void setHoldResultsOpenOverStatementClose(boolean flag) { + // not runtime configurable + + } + + public void setIgnoreNonTxTables(boolean property) { + // not runtime configurable + + } + + public void setIncludeInnodbStatusInDeadlockExceptions(boolean flag) { + // not runtime configurable + + } + + public void setInitialTimeout(int property) { + // not runtime configurable + + } + + public void setInteractiveClient(boolean property) { + // not runtime configurable + + } + + public void setIsInteractiveClient(boolean property) { + // not runtime configurable + + } + + public void setJdbcCompliantTruncation(boolean flag) { + // not runtime configurable + + } + + public void setJdbcCompliantTruncationForReads( + boolean jdbcCompliantTruncationForReads) { + // not runtime configurable + + } + + public void setLargeRowSizeThreshold(String value) { + // not runtime configurable + + } + + public void setLoadBalanceStrategy(String strategy) { + // not runtime configurable + + } + + public void setLocalSocketAddress(String address) { + // not runtime configurable + + } + + public void setLocatorFetchBufferSize(String value) throws SQLException { + // not runtime configurable + + } + + public void setLogSlowQueries(boolean flag) { + // not runtime configurable + + } + + public void setLogXaCommands(boolean flag) { + // not runtime configurable + + } + + public void setLogger(String property) { + // not runtime configurable + + } + + public void setLoggerClassName(String className) { + // not runtime configurable + + } + + public void setMaintainTimeStats(boolean flag) { + // not runtime configurable + + } + + public void setMaxQuerySizeToLog(int sizeInBytes) { + // not runtime configurable + + } + + public void setMaxReconnects(int property) { + // not runtime configurable + + } + + public void setMaxRows(int property) { + // not runtime configurable + + } + + public void setMetadataCacheSize(int value) { + // not runtime configurable + + } + + public void setNetTimeoutForStreamingResults(int value) { + // not runtime configurable + + } + + public void setNoAccessToProcedureBodies(boolean flag) { + // not runtime configurable + + } + + public void setNoDatetimeStringSync(boolean flag) { + // not runtime configurable + + } + + public void setNoTimezoneConversionForTimeType(boolean flag) { + // not runtime configurable + + } + + public void setNullCatalogMeansCurrent(boolean value) { + // not runtime configurable + + } + + public void setNullNamePatternMatchesAll(boolean value) { + // not runtime configurable + + } + + public void setOverrideSupportsIntegrityEnhancementFacility(boolean flag) { + // not runtime configurable + + } + + public void setPacketDebugBufferSize(int size) { + // not runtime configurable + + } + + public void setPadCharsWithSpace(boolean flag) { + // not runtime configurable + + } + + public void setParanoid(boolean property) { + // not runtime configurable + + } + + public void setPedantic(boolean property) { + // not runtime configurable + + } + + public void setPinGlobalTxToPhysicalConnection(boolean flag) { + // not runtime configurable + + } + + public void setPopulateInsertRowWithDefaultValues(boolean flag) { + // not runtime configurable + + } + + public void setPrepStmtCacheSize(int cacheSize) { + // not runtime configurable + + } + + public void setPrepStmtCacheSqlLimit(int sqlLimit) { + // not runtime configurable + + } + + public void setPreparedStatementCacheSize(int cacheSize) { + // not runtime configurable + + } + + public void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) { + // not runtime configurable + + } + + public void setProcessEscapeCodesForPrepStmts(boolean flag) { + // not runtime configurable + + } + + public void setProfileSQL(boolean flag) { + // not runtime configurable + + } + + public void setProfileSql(boolean property) { + // not runtime configurable + + } + + public void setProfilerEventHandler(String handler) { + // not runtime configurable + + } + + public void setPropertiesTransform(String value) { + // not runtime configurable + + } + + public void setQueriesBeforeRetryMaster(int property) { + // not runtime configurable + + } + + public void setReconnectAtTxEnd(boolean property) { + // not runtime configurable + + } + + public void setRelaxAutoCommit(boolean property) { + // not runtime configurable + + } + + public void setReportMetricsIntervalMillis(int millis) { + // not runtime configurable + + } + + public void setRequireSSL(boolean property) { + // not runtime configurable + + } + + public void setResourceId(String resourceId) { + // not runtime configurable + + } + + public void setResultSetSizeThreshold(int threshold) { + // not runtime configurable + + } + + public void setRetainStatementAfterResultSetClose(boolean flag) { + // not runtime configurable + + } + + public void setRewriteBatchedStatements(boolean flag) { + // not runtime configurable + + } + + public void setRollbackOnPooledClose(boolean flag) { + // not runtime configurable + + } + + public void setRoundRobinLoadBalance(boolean flag) { + // not runtime configurable + + } + + public void setRunningCTS13(boolean flag) { + // not runtime configurable + + } + + public void setSecondsBeforeRetryMaster(int property) { + // not runtime configurable + + } + + public void setSelfDestructOnPingMaxOperations(int maxOperations) { + // not runtime configurable + + } + + public void setSelfDestructOnPingSecondsLifetime(int seconds) { + // not runtime configurable + + } + + public void setServerTimezone(String property) { + // not runtime configurable + + } + + public void setSessionVariables(String variables) { + // not runtime configurable + + } + + public void setSlowQueryThresholdMillis(int millis) { + // not runtime configurable + + } + + public void setSlowQueryThresholdNanos(long nanos) { + // not runtime configurable + + } + + public void setSocketFactory(String name) { + // not runtime configurable + + } + + public void setSocketFactoryClassName(String property) { + // not runtime configurable + + } + + public void setSocketTimeout(int property) { + // not runtime configurable + + } + + public void setStatementInterceptors(String value) { + // not runtime configurable + + } + + public void setStrictFloatingPoint(boolean property) { + // not runtime configurable + + } + + public void setStrictUpdates(boolean property) { + // not runtime configurable + + } + + public void setTcpKeepAlive(boolean flag) { + // not runtime configurable + + } + + public void setTcpNoDelay(boolean flag) { + // not runtime configurable + + } + + public void setTcpRcvBuf(int bufSize) { + // not runtime configurable + + } + + public void setTcpSndBuf(int bufSize) { + // not runtime configurable + + } + + public void setTcpTrafficClass(int classFlags) { + // not runtime configurable + + } + + public void setTinyInt1isBit(boolean flag) { + // not runtime configurable + + } + + public void setTraceProtocol(boolean flag) { + // not runtime configurable + + } + + public void setTransformedBitIsBoolean(boolean flag) { + // not runtime configurable + + } + + public void setTreatUtilDateAsTimestamp(boolean flag) { + // not runtime configurable + + } + + public void setTrustCertificateKeyStorePassword(String value) { + // not runtime configurable + + } + + public void setTrustCertificateKeyStoreType(String value) { + // not runtime configurable + + } + + public void setTrustCertificateKeyStoreUrl(String value) { + // not runtime configurable + + } + + public void setUltraDevHack(boolean flag) { + // not runtime configurable + + } + + public void setUseBlobToStoreUTF8OutsideBMP(boolean flag) { + // not runtime configurable + + } + + public void setUseCompression(boolean property) { + // not runtime configurable + + } + + public void setUseConfigs(String configs) { + // not runtime configurable + + } + + public void setUseCursorFetch(boolean flag) { + // not runtime configurable + + } + + public void setUseDirectRowUnpack(boolean flag) { + // not runtime configurable + + } + + public void setUseDynamicCharsetInfo(boolean flag) { + // not runtime configurable + + } + + public void setUseFastDateParsing(boolean flag) { + // not runtime configurable + + } + + public void setUseFastIntParsing(boolean flag) { + // not runtime configurable + + } + + public void setUseGmtMillisForDatetimes(boolean flag) { + // not runtime configurable + + } + + public void setUseHostsInPrivileges(boolean property) { + // not runtime configurable + + } + + public void setUseInformationSchema(boolean flag) { + // not runtime configurable + + } + + public void setUseJDBCCompliantTimezoneShift(boolean flag) { + // not runtime configurable + + } + + public void setUseJvmCharsetConverters(boolean flag) { + // not runtime configurable + + } + + public void setUseLegacyDatetimeCode(boolean flag) { + // not runtime configurable + + } + + public void setUseLocalSessionState(boolean flag) { + // not runtime configurable + + } + + public void setUseNanosForElapsedTime(boolean flag) { + // not runtime configurable + + } + + public void setUseOldAliasMetadataBehavior(boolean flag) { + // not runtime configurable + + } + + public void setUseOldUTF8Behavior(boolean flag) { + // not runtime configurable + + } + + public void setUseOnlyServerErrorMessages(boolean flag) { + // not runtime configurable + + } + + public void setUseReadAheadInput(boolean flag) { + // not runtime configurable + + } + + public void setUseSSL(boolean property) { + // not runtime configurable + + } + + public void setUseSSPSCompatibleTimezoneShift(boolean flag) { + // not runtime configurable + + } + + public void setUseServerPrepStmts(boolean flag) { + // not runtime configurable + + } + + public void setUseServerPreparedStmts(boolean flag) { + // not runtime configurable + + } + + public void setUseSqlStateCodes(boolean flag) { + // not runtime configurable + + } + + public void setUseStreamLengthsInPrepStmts(boolean property) { + // not runtime configurable + + } + + public void setUseTimezone(boolean property) { + // not runtime configurable + + } + + public void setUseUltraDevWorkAround(boolean property) { + // not runtime configurable + + } + + public void setUseUnbufferedInput(boolean flag) { + // not runtime configurable + + } + + public void setUseUnicode(boolean flag) { + // not runtime configurable + + } + + public void setUseUsageAdvisor(boolean useUsageAdvisorFlag) { + // not runtime configurable + + } + + public void setUtf8OutsideBmpExcludedColumnNamePattern(String regexPattern) { + // not runtime configurable + + } + + public void setUtf8OutsideBmpIncludedColumnNamePattern(String regexPattern) { + // not runtime configurable + + } + + public void setVerifyServerCertificate(boolean flag) { + // not runtime configurable + + } + + public void setYearIsDateType(boolean flag) { + // not runtime configurable + + } + + public void setZeroDateTimeBehavior(String behavior) { + // not runtime configurable + + } + + public boolean useUnbufferedInput() { + return getCurrentConnection().useUnbufferedInput(); + } + + public boolean isSameResource(Connection c) { + return getCurrentConnection().isSameResource(c); + } + + public void setInGlobalTx(boolean flag) { + getCurrentConnection().setInGlobalTx(flag); + } + + public boolean getUseColumnNamesInFindColumn() { + return getCurrentConnection().getUseColumnNamesInFindColumn(); + } + + public void setUseColumnNamesInFindColumn(boolean flag) { + // not runtime configurable + } + + public boolean getUseLocalTransactionState() { + return getCurrentConnection().getUseLocalTransactionState(); + } + + public void setUseLocalTransactionState(boolean flag) { + // not runtime configurable + + } + + public boolean getCompensateOnDuplicateKeyUpdateCounts() { + return getCurrentConnection().getCompensateOnDuplicateKeyUpdateCounts(); + } + + public void setCompensateOnDuplicateKeyUpdateCounts(boolean flag) { + // not runtime configurable + + } + + public boolean getUseAffectedRows() { + return getCurrentConnection().getUseAffectedRows(); + } + + public void setUseAffectedRows(boolean flag) { + // not runtime configurable + + } + + public String getPasswordCharacterEncoding() { + return getCurrentConnection().getPasswordCharacterEncoding(); + } + + public void setPasswordCharacterEncoding(String characterSet) { + getCurrentConnection().setPasswordCharacterEncoding(characterSet); + } + + public int getAutoIncrementIncrement() { + return getCurrentConnection().getAutoIncrementIncrement(); + } + + public int getLoadBalanceBlacklistTimeout() { + return getCurrentConnection().getLoadBalanceBlacklistTimeout(); + } + + public void setLoadBalanceBlacklistTimeout(int loadBalanceBlacklistTimeout) throws SQLException { + getCurrentConnection().setLoadBalanceBlacklistTimeout(loadBalanceBlacklistTimeout); + } + + public int getLoadBalancePingTimeout() { + return getCurrentConnection().getLoadBalancePingTimeout(); + } + + public void setLoadBalancePingTimeout(int loadBalancePingTimeout) throws SQLException { + getCurrentConnection().setLoadBalancePingTimeout(loadBalancePingTimeout); + } + + public boolean getLoadBalanceValidateConnectionOnSwapServer() { + return getCurrentConnection().getLoadBalanceValidateConnectionOnSwapServer(); + } + + public void setLoadBalanceValidateConnectionOnSwapServer(boolean loadBalanceValidateConnectionOnSwapServer) { + getCurrentConnection().setLoadBalanceValidateConnectionOnSwapServer(loadBalanceValidateConnectionOnSwapServer); + } + + public int getRetriesAllDown() { + return getCurrentConnection().getRetriesAllDown(); + } + + public void setRetriesAllDown(int retriesAllDown) throws SQLException { + getCurrentConnection().setRetriesAllDown(retriesAllDown); + } + + public ExceptionInterceptor getExceptionInterceptor() { + return getCurrentConnection().getExceptionInterceptor(); + } + + public String getExceptionInterceptors() { + return getCurrentConnection().getExceptionInterceptors(); + } + + public void setExceptionInterceptors(String exceptionInterceptors) { + getCurrentConnection().setExceptionInterceptors(exceptionInterceptors); + } + + public boolean getQueryTimeoutKillsConnection() { + return getCurrentConnection().getQueryTimeoutKillsConnection(); + } + + public void setQueryTimeoutKillsConnection( + boolean queryTimeoutKillsConnection) { + getCurrentConnection().setQueryTimeoutKillsConnection(queryTimeoutKillsConnection); + } + + public boolean hasSameProperties(Connection c) { + return this.masterConnection.hasSameProperties(c) && + this.slavesConnection.hasSameProperties(c); + } + + public Properties getProperties() { + Properties props = new Properties(); + props.putAll(this.masterConnection.getProperties()); + props.putAll(this.slavesConnection.getProperties()); + + return props; + } + + public String getHost() { + return getCurrentConnection().getHost(); + } + + public void setProxy(MySQLConnection proxy) { + getCurrentConnection().setProxy(proxy); + } + + public boolean getRetainStatementAfterResultSetClose() { + return getCurrentConnection().getRetainStatementAfterResultSetClose(); + } + + public int getMaxAllowedPacket() { + return getCurrentConnection().getMaxAllowedPacket(); + } + + public String getLoadBalanceConnectionGroup() { + return getCurrentConnection().getLoadBalanceConnectionGroup(); + } + + public boolean getLoadBalanceEnableJMX() { + return getCurrentConnection().getLoadBalanceEnableJMX(); + } + + public String getLoadBalanceExceptionChecker() { + return currentConnection + .getLoadBalanceExceptionChecker(); + } + + public String getLoadBalanceSQLExceptionSubclassFailover() { + return currentConnection + .getLoadBalanceSQLExceptionSubclassFailover(); + } + + public String getLoadBalanceSQLStateFailover() { + return currentConnection + .getLoadBalanceSQLStateFailover(); + } + + public void setLoadBalanceConnectionGroup(String loadBalanceConnectionGroup) { + currentConnection + .setLoadBalanceConnectionGroup(loadBalanceConnectionGroup); + + } + + public void setLoadBalanceEnableJMX(boolean loadBalanceEnableJMX) { + currentConnection + .setLoadBalanceEnableJMX(loadBalanceEnableJMX); + + } + + public void setLoadBalanceExceptionChecker( + String loadBalanceExceptionChecker) { + currentConnection + .setLoadBalanceExceptionChecker(loadBalanceExceptionChecker); + + } + + public void setLoadBalanceSQLExceptionSubclassFailover( + String loadBalanceSQLExceptionSubclassFailover) { + currentConnection + .setLoadBalanceSQLExceptionSubclassFailover(loadBalanceSQLExceptionSubclassFailover); + + } + + public void setLoadBalanceSQLStateFailover( + String loadBalanceSQLStateFailover) { + currentConnection + .setLoadBalanceSQLStateFailover(loadBalanceSQLStateFailover); + + } + + public String getLoadBalanceAutoCommitStatementRegex() { + return getCurrentConnection().getLoadBalanceAutoCommitStatementRegex(); + } + + public int getLoadBalanceAutoCommitStatementThreshold() { + return getCurrentConnection().getLoadBalanceAutoCommitStatementThreshold(); + } + + public void setLoadBalanceAutoCommitStatementRegex( + String loadBalanceAutoCommitStatementRegex) { + getCurrentConnection().setLoadBalanceAutoCommitStatementRegex(loadBalanceAutoCommitStatementRegex); + + } + + public void setLoadBalanceAutoCommitStatementThreshold( + int loadBalanceAutoCommitStatementThreshold) throws SQLException { + getCurrentConnection().setLoadBalanceAutoCommitStatementThreshold(loadBalanceAutoCommitStatementThreshold); + + } + + public void setTypeMap(Map> map) throws SQLException { + // TODO Auto-generated method stub + + } + + public boolean getIncludeThreadDumpInDeadlockExceptions() { + return getCurrentConnection().getIncludeThreadDumpInDeadlockExceptions(); + } + + public void setIncludeThreadDumpInDeadlockExceptions(boolean flag) { + getCurrentConnection().setIncludeThreadDumpInDeadlockExceptions(flag); + + } + + public boolean getIncludeThreadNamesAsStatementComment() { + return getCurrentConnection().getIncludeThreadNamesAsStatementComment(); + } + + public void setIncludeThreadNamesAsStatementComment(boolean flag) { + getCurrentConnection().setIncludeThreadNamesAsStatementComment(flag); + } + + public boolean isServerLocal() throws SQLException { + return getCurrentConnection().isServerLocal(); + } + + public void setAuthenticationPlugins(String authenticationPlugins) { + getCurrentConnection().setAuthenticationPlugins(authenticationPlugins); + } + + public String getAuthenticationPlugins() { + return getCurrentConnection().getAuthenticationPlugins(); + } + + public void setDisabledAuthenticationPlugins( + String disabledAuthenticationPlugins) { + getCurrentConnection().setDisabledAuthenticationPlugins(disabledAuthenticationPlugins); + } + + public String getDisabledAuthenticationPlugins() { + return getCurrentConnection().getDisabledAuthenticationPlugins(); + } + + public void setDefaultAuthenticationPlugin( + String defaultAuthenticationPlugin) { + getCurrentConnection().setDefaultAuthenticationPlugin(defaultAuthenticationPlugin); + } + + public String getDefaultAuthenticationPlugin() { + return getCurrentConnection().getDefaultAuthenticationPlugin(); + } + + public void setParseInfoCacheFactory(String factoryClassname) { + getCurrentConnection().setParseInfoCacheFactory(factoryClassname); + } + + public String getParseInfoCacheFactory() { + return getCurrentConnection().getParseInfoCacheFactory(); + } + + public void setSchema(String schema) throws SQLException { + getCurrentConnection().setSchema(schema); + } + + public String getSchema() throws SQLException { + return getCurrentConnection().getSchema(); + } + + public void abort(Executor executor) throws SQLException { + getCurrentConnection().abort(executor); + if(this.connectionGroup != null) { + this.connectionGroup.handleCloseConnection(this); + } + } + + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException { + getCurrentConnection().setNetworkTimeout(executor, milliseconds); + } + + public int getNetworkTimeout() throws SQLException { + return getCurrentConnection().getNetworkTimeout(); + } + + public void setServerConfigCacheFactory(String factoryClassname) { + getCurrentConnection().setServerConfigCacheFactory(factoryClassname); + } + + public String getServerConfigCacheFactory() { + return getCurrentConnection().getServerConfigCacheFactory(); + } + + public void setDisconnectOnExpiredPasswords(boolean disconnectOnExpiredPasswords) { + getCurrentConnection().setDisconnectOnExpiredPasswords(disconnectOnExpiredPasswords); + } + + public boolean getDisconnectOnExpiredPasswords() { + return getCurrentConnection().getDisconnectOnExpiredPasswords(); + } + + public void setGetProceduresReturnsFunctions(boolean getProcedureReturnsFunctions) { + getCurrentConnection().setGetProceduresReturnsFunctions(getProcedureReturnsFunctions); + } + + public boolean getGetProceduresReturnsFunctions() { + return getCurrentConnection().getGetProceduresReturnsFunctions(); + } + + public void abortInternal() throws SQLException { + getCurrentConnection().abortInternal(); + if(this.connectionGroup != null) { + this.connectionGroup.handleCloseConnection(this); + } + } + + public void checkClosed() throws SQLException { + getCurrentConnection().checkClosed(); + } + + public Object getConnectionMutex() { + return getCurrentConnection().getConnectionMutex(); + } + + public boolean getAllowMasterDownConnections() { + return this.allowMasterDownConnections; + } + + public void setAllowMasterDownConnections(boolean connectIfMasterDown) { + this.allowMasterDownConnections = connectIfMasterDown; + } + + public boolean getReplicationEnableJMX() { + return this.enableJMX; + } + + public void setReplicationEnableJMX(boolean replicationEnableJMX) { + this.enableJMX = replicationEnableJMX; + + } + + + public String getConnectionAttributes() throws SQLException { + return getCurrentConnection().getConnectionAttributes(); + } + + public void setDetectCustomCollations(boolean detectCustomCollations) { + getCurrentConnection().setDetectCustomCollations(detectCustomCollations); + } + + public boolean getDetectCustomCollations() { + return getCurrentConnection().getDetectCustomCollations(); + } + + public int getSessionMaxRows() { + return getCurrentConnection().getSessionMaxRows(); + } + + public void setSessionMaxRows(int max) throws SQLException { + getCurrentConnection().setSessionMaxRows(max); + } + + public String getServerRSAPublicKeyFile() { + return getCurrentConnection().getServerRSAPublicKeyFile(); + } + + public void setServerRSAPublicKeyFile(String serverRSAPublicKeyFile) throws SQLException { + getCurrentConnection().setServerRSAPublicKeyFile(serverRSAPublicKeyFile); + } + + public boolean getAllowPublicKeyRetrieval() { + return getCurrentConnection().getAllowPublicKeyRetrieval(); + } + + public void setAllowPublicKeyRetrieval(boolean allowPublicKeyRetrieval) throws SQLException { + getCurrentConnection().setAllowPublicKeyRetrieval(allowPublicKeyRetrieval); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnectionGroup.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnectionGroup.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnectionGroup.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,194 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Group of connection objects which can be configured as a group. This is used + * for promotion/demotion of slaves and masters in a replication configuration, + * and for exposing metrics around replication-aware connections. + * + * @author Todd Farmer + * + */ +public class ReplicationConnectionGroup { + + private String groupName; + private long connections = 0; + private long slavesAdded = 0; + private long slavesRemoved = 0; + private long slavesPromoted = 0; + private long activeConnections = 0; + private HashMap replicationConnections = new HashMap(); + private Set slaveHostList = new HashSet(); + private boolean isInitialized = false; + private Set masterHostList = new HashSet(); + + ReplicationConnectionGroup(String groupName) { + this.groupName = groupName; + } + + public long getConnectionCount() { + return this.connections; + } + + public long registerReplicationConnection(ReplicationConnection conn, + List localMasterList, List localSlaveList) { + long currentConnectionId; + + synchronized (this) { + if (!this.isInitialized) { + if(localMasterList != null) { + this.masterHostList.addAll(localMasterList); + } + if(localSlaveList != null) { + this.slaveHostList.addAll(localSlaveList); + } + this.isInitialized = true; + } + currentConnectionId = ++connections; + this.replicationConnections.put(Long.valueOf(currentConnectionId), + conn); + } + this.activeConnections++; + + + return currentConnectionId; + + } + + public String getGroupName() { + return this.groupName; + } + + + public Collection getMasterHosts() { + return this.masterHostList; + } + + public Collection getSlaveHosts() { + return this.slaveHostList; + } + + public void addSlaveHost(String host) throws SQLException { + // only do this if addition was successful: + if (this.slaveHostList.add(host)) { + this.slavesAdded++; + } + // add the slave to all connections: + for (ReplicationConnection c : this.replicationConnections.values()) { + c.addSlaveHost(host); + } + + } + + public void handleCloseConnection(ReplicationConnection conn) { + this.replicationConnections.remove(conn.getConnectionGroupId()); + this.activeConnections--; + } + + public void removeSlaveHost(String host, boolean closeGently) throws SQLException { + if (this.slaveHostList.remove(host)) { + this.slavesRemoved++; + } + for (ReplicationConnection c : this.replicationConnections.values()) { + c.removeSlave(host, closeGently); + } + } + + public void promoteSlaveToMaster(String host) throws SQLException { + this.slaveHostList.remove(host); + this.masterHostList.add(host); + for (ReplicationConnection c : this.replicationConnections.values()) { + c.promoteSlaveToMaster(host); + } + + this.slavesPromoted++; + } + + public void removeMasterHost(String host) throws SQLException { + this.removeMasterHost(host, true); + } + + public void removeMasterHost(String host, boolean closeGently) throws SQLException { + if(this.masterHostList.remove(host)) { + + } + for (ReplicationConnection c : this.replicationConnections.values()) { + c.removeMasterHost(host, closeGently); + } + + } + + public int getConnectionCountWithHostAsSlave(String host) { + int matched = 0; + + for (ReplicationConnection c : this.replicationConnections.values()) { + if(c.isHostSlave(host)) { + matched++; + } + } + return matched; + } + public int getConnectionCountWithHostAsMaster(String host) { + int matched = 0; + + for (ReplicationConnection c : this.replicationConnections.values()) { + if(c.isHostMaster(host)) { + matched++; + } + } + return matched; + } + + + + public long getNumberOfSlavesAdded() { + return this.slavesAdded; + } + + public long getNumberOfSlavesRemoved() { + return this.slavesRemoved; + } + + public long getNumberOfSlavePromotions() { + return this.slavesPromoted; + } + + public long getTotalConnectionCount() { + return this.connections; + } + + public long getActiveConnectionCount() { + return this.activeConnections; + } + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnectionGroupManager.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnectionGroupManager.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationConnectionGroupManager.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,217 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +public class ReplicationConnectionGroupManager { + private static HashMap GROUP_MAP = new HashMap(); + + private static com.mysql.jdbc.jmx.ReplicationGroupManager mbean = new com.mysql.jdbc.jmx.ReplicationGroupManager(); + + private static boolean hasRegisteredJmx = false; + + public static synchronized ReplicationConnectionGroup getConnectionGroupInstance( + String groupName) { + if (GROUP_MAP.containsKey(groupName)) { + return GROUP_MAP.get(groupName); + } + ReplicationConnectionGroup group = new ReplicationConnectionGroup( + groupName); + GROUP_MAP.put(groupName, group); + return group; + } + + public static void registerJmx() throws SQLException { + + if (hasRegisteredJmx) { + return; + } + + mbean.registerJmx(); + hasRegisteredJmx = true; + } + + public static ReplicationConnectionGroup getConnectionGroup(String groupName) { + return GROUP_MAP.get(groupName); + } + + public static Collection getGroupsMatching( + String group) { + if (group == null || group.equals("")) { + Set s = new HashSet(); + + s.addAll(GROUP_MAP.values()); + return s; + } + Set s = new HashSet(); + ReplicationConnectionGroup o = GROUP_MAP.get(group); + if (o != null) { + s.add(o); + } + return s; + + } + + public static void addSlaveHost(String group, String host) throws SQLException { + Collection s = getGroupsMatching(group); + for (ReplicationConnectionGroup cg : s) { + cg.addSlaveHost(host); + } + } + + public static void removeSlaveHost(String group, String host) + throws SQLException { + removeSlaveHost(group, host, true); + } + + public static void removeSlaveHost(String group, String host, + boolean closeGently) throws SQLException { + Collection s = getGroupsMatching(group); + for (ReplicationConnectionGroup cg : s) { + cg.removeSlaveHost(host, closeGently); + } + } + + public static void promoteSlaveToMaster(String group, String newMasterHost) throws SQLException { + Collection s = getGroupsMatching(group); + for (ReplicationConnectionGroup cg : s) { + cg.promoteSlaveToMaster(newMasterHost); + } + + } + + public static long getSlavePromotionCount(String group) throws SQLException { + Collection s = getGroupsMatching(group); + long promoted = 0; + for (ReplicationConnectionGroup cg : s) { + long tmp = cg.getNumberOfSlavePromotions(); + if(tmp > promoted) { + promoted = tmp; + } + } + return promoted; + + } + + + public static void removeMasterHost(String group, String host) throws SQLException { + removeMasterHost(group, host, true); + } + + public static void removeMasterHost(String group, String host, boolean closeGently) throws SQLException { + Collection s = getGroupsMatching(group); + for (ReplicationConnectionGroup cg : s) { + cg.removeMasterHost(host, closeGently); + } + } + + public static String getRegisteredReplicationConnectionGroups() { + Collection s = getGroupsMatching(null); + StringBuffer sb = new StringBuffer(); + String sep = ""; + for (ReplicationConnectionGroup cg : s) { + String group = cg.getGroupName(); + sb.append(sep); + sb.append(group); + sep = ","; + } + return sb.toString(); + + } + + + public static int getNumberOfMasterPromotion(String groupFilter) { + int total = 0; + Collection s = getGroupsMatching(groupFilter); + for(ReplicationConnectionGroup cg : s) { + total += cg.getNumberOfSlavePromotions(); + } + return total; + } + + + public static int getConnectionCountWithHostAsSlave(String groupFilter, String host) { + int total = 0; + Collection s = getGroupsMatching(groupFilter); + for(ReplicationConnectionGroup cg : s) { + total += cg.getConnectionCountWithHostAsSlave(host); + } + return total; + } + + public static int getConnectionCountWithHostAsMaster(String groupFilter, String host) { + int total = 0; + Collection s = getGroupsMatching(groupFilter); + for(ReplicationConnectionGroup cg : s) { + total += cg.getConnectionCountWithHostAsMaster(host); + } + return total; + } + + public static Collection getSlaveHosts(String groupFilter) { + Collection s = getGroupsMatching(groupFilter); + Collection hosts = new ArrayList(); + for(ReplicationConnectionGroup cg : s) { + hosts.addAll(cg.getSlaveHosts()); + } + return hosts; + } + + public static Collection getMasterHosts(String groupFilter) { + Collection s = getGroupsMatching(groupFilter); + Collection hosts = new ArrayList(); + for(ReplicationConnectionGroup cg : s) { + hosts.addAll(cg.getMasterHosts()); + } + return hosts; + } + + public static long getTotalConnectionCount(String group) { + long connections = 0; + Collection s = getGroupsMatching(group); + for(ReplicationConnectionGroup cg : s) { + connections += cg.getTotalConnectionCount(); + } + return connections; + } + + public static long getActiveConnectionCount(String group) { + long connections = 0; + Collection s = getGroupsMatching(group); + for(ReplicationConnectionGroup cg : s) { + connections += cg.getActiveConnectionCount(); + } + return connections; + + } + + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationDriver.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationDriver.java (.../ReplicationDriver.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ReplicationDriver.java (.../ReplicationDriver.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetImpl.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetImpl.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetImpl.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,8754 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Constructor; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.Array; +import java.sql.Date; +import java.sql.Ref; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.util.TreeMap; + +import com.mysql.jdbc.log.LogUtils; +import com.mysql.jdbc.profiler.ProfilerEvent; +import com.mysql.jdbc.profiler.ProfilerEventHandler; + +/** + * A ResultSet provides access to a table of data generated by executing a + * Statement. The table rows are retrieved in sequence. Within a row its column + * values can be accessed in any order. + * + *

+ * A ResultSet maintains a cursor pointing to its current row of data. Initially + * the cursor is positioned before the first row. The 'next' method moves the + * cursor to the next row. + *

+ * + *

+ * The getXXX methods retrieve column values for the current row. You can + * retrieve values either using the index number of the column, or by using the + * name of the column. In general using the column index will be more efficient. + * Columns are numbered from 1. + *

+ * + *

+ * For maximum portability, ResultSet columns within each row should be read in + * left-to-right order and each column should be read only once. + *

+ * + *

+ * For the getXXX methods, the JDBC driver attempts to convert the underlying + * data to the specified Java type and returns a suitable Java value. See the + * JDBC specification for allowable mappings from SQL types to Java types with + * the ResultSet getXXX methods. + *

+ * + *

+ * Column names used as input to getXXX methods are case insenstive. When + * performing a getXXX using a column name, if several columns have the same + * name, then the value of the first matching column will be returned. The + * column name option is designed to be used when column names are used in the + * SQL Query. For columns that are NOT explicitly named in the query, it is best + * to use column numbers. If column names were used there is no way for the + * programmer to guarentee that they actually refer to the intended columns. + *

+ * + *

+ * A ResultSet is automatically closed by the Statement that generated it when + * that Statement is closed, re-executed, or is used to retrieve the next result + * from a sequence of multiple results. + *

+ * + *

+ * The number, types and properties of a ResultSet's columns are provided by the + * ResultSetMetaData object returned by the getMetaData method. + *

+ * + * @author Mark Matthews + * @version $Id$ + * + * @see ResultSetMetaData + * @see java.sql.ResultSet + */ +public class ResultSetImpl implements ResultSetInternalMethods { + + private static final Constructor JDBC_4_RS_4_ARG_CTOR; + private static final Constructor JDBC_4_RS_6_ARG_CTOR;; + private static final Constructor JDBC_4_UPD_RS_6_ARG_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_RS_4_ARG_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4ResultSet").getConstructor( + new Class[] { Long.TYPE, Long.TYPE, + MySQLConnection.class, + com.mysql.jdbc.StatementImpl.class }); + JDBC_4_RS_6_ARG_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4ResultSet").getConstructor( + new Class[] { String.class, Field[].class, + RowData.class, + MySQLConnection.class, + com.mysql.jdbc.StatementImpl.class }); + JDBC_4_UPD_RS_6_ARG_CTOR = Class.forName( + "com.mysql.jdbc.JDBC4UpdatableResultSet") + .getConstructor( + new Class[] { String.class, Field[].class, + RowData.class, + MySQLConnection.class, + com.mysql.jdbc.StatementImpl.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_RS_4_ARG_CTOR = null; + JDBC_4_RS_6_ARG_CTOR = null; + JDBC_4_UPD_RS_6_ARG_CTOR = null; + } + } + + /** + * Epsillon between Float.MIN_VALUE and the double representation of said value. + */ + protected static final double MIN_DIFF_PREC = Float.parseFloat(Float.toString(Float.MIN_VALUE)) + - Double.parseDouble(Float.toString(Float.MIN_VALUE)); + + /** + * Epsillon between Float.MAX_VALUE and the double representation of said value. + */ + protected static final double MAX_DIFF_PREC = Float.parseFloat(Float.toString(Float.MAX_VALUE)) + - Double.parseDouble(Float.toString(Float.MAX_VALUE)); + + /** Counter used to generate IDs for profiling. */ + static int resultCounter = 1; + + /** + * Converts the given value as a java long, to an 'unsigned' long, using the + * java.math.BigInteger class. + */ + protected static BigInteger convertLongToUlong(long longVal) { + byte[] asBytes = new byte[8]; + asBytes[7] = (byte) (longVal & 0xff); + asBytes[6] = (byte) (longVal >>> 8); + asBytes[5] = (byte) (longVal >>> 16); + asBytes[4] = (byte) (longVal >>> 24); + asBytes[3] = (byte) (longVal >>> 32); + asBytes[2] = (byte) (longVal >>> 40); + asBytes[1] = (byte) (longVal >>> 48); + asBytes[0] = (byte) (longVal >>> 56); + + return new BigInteger(1, asBytes); + } + + /** The catalog that was in use when we were created */ + protected String catalog = null; + + /** Map column names (and all of their permutations) to column indices */ + protected Map columnLabelToIndex = null; + + /** The above map is a case-insensitive tree-map, it can be slow, this caches + * lookups into that map, because the other alternative is to create new + * object instances for every call to findColumn().... + */ + protected Map columnToIndexCache = null; + + /** Keep track of columns accessed */ + protected boolean[] columnUsed = null; + + /** The Connection instance that created us */ + protected volatile MySQLConnection connection; // The connection that + // created us + + protected long connectionId = 0; + + /** The current row #, -1 == before start of result set */ + protected int currentRow = -1; // Cursor to current row; + + TimeZone defaultTimeZone; + + /** Are we in the middle of doing updates to the current row? */ + protected boolean doingUpdates = false; + + protected ProfilerEventHandler eventSink = null; + + Calendar fastDateCal = null; + + /** The direction to fetch rows (always FETCH_FORWARD) */ + protected int fetchDirection = FETCH_FORWARD; + + /** The number of rows to fetch in one go... */ + protected int fetchSize = 0; + + /** The fields for this result set */ + protected Field[] fields; // The fields + + /** + * First character of the query that created this result set...Used to + * determine whether or not to parse server info messages in certain + * circumstances. + */ + protected char firstCharOfQuery; + + /** Map of fully-specified column names to column indices */ + protected Map fullColumnNameToIndex = null; + + protected Map columnNameToIndex = null; + + protected boolean hasBuiltIndexMapping = false; + + /** + * Is the data stored as strings (default) or natively (which is the case + * with results from PrepStmts) + */ + protected boolean isBinaryEncoded = false; + + /** Has this result set been closed? */ + protected boolean isClosed = false; + + protected ResultSetInternalMethods nextResultSet = null; + + /** Are we on the insert row? */ + protected boolean onInsertRow = false; + + /** The statement that created us */ + protected com.mysql.jdbc.StatementImpl owningStatement; + + /** + * StackTrace generated where ResultSet was created... used when profiling + */ + protected String pointOfOrigin; + + /** Are we tracking items for profileSql? */ + protected boolean profileSql = false; + + /** + * Do we actually contain rows, or just information about + * UPDATE/INSERT/DELETE? + */ + protected boolean reallyResult = false; + + /** The id (used when profiling) to identify us */ + protected int resultId; + + /** Are we read-only or updatable? */ + protected int resultSetConcurrency = 0; + + /** Are we scroll-sensitive/insensitive? */ + protected int resultSetType = 0; + + /** The actual rows */ + protected RowData rowData; // The results + + /** + * Any info message from the server that was created while generating this + * result set (if 'info parsing' is enabled for the connection). + */ + protected String serverInfo = null; + + PreparedStatement statementUsedForFetchingRows; + + /** Pointer to current row data */ + protected ResultSetRow thisRow = null; // Values for current row + + // These are longs for + // recent versions of the MySQL server. + // + // They get reduced to ints via the JDBC API, + // but can be retrieved through a MySQLStatement + // in their entirety. + // + + /** How many rows were affected by UPDATE/INSERT/DELETE? */ + protected long updateCount; + + /** Value generated for AUTO_INCREMENT columns */ + protected long updateId = -1; + + private boolean useStrictFloatingPoint = false; + + protected boolean useUsageAdvisor = false; + + /** The warning chain */ + protected java.sql.SQLWarning warningChain = null; + + /** Did the previous value retrieval find a NULL? */ + protected boolean wasNullFlag = false; + + protected java.sql.Statement wrapperStatement; + + protected boolean retainOwningStatement; + + protected Calendar gmtCalendar = null; + + protected boolean useFastDateParsing = false; + + private boolean padCharsWithSpace = false; + + private boolean jdbcCompliantTruncationForReads; + + private boolean useFastIntParsing = true; + private boolean useColumnNamesInFindColumn; + + private ExceptionInterceptor exceptionInterceptor; + + final static char[] EMPTY_SPACE = new char[255]; + + static { + for (int i = 0; i < EMPTY_SPACE.length; i++) { + EMPTY_SPACE[i] = ' '; + } + } + + protected static ResultSetImpl getInstance(long updateCount, long updateID, + MySQLConnection conn, StatementImpl creatorStmt) throws SQLException { + if (!Util.isJdbc4()) { + return new ResultSetImpl(updateCount, updateID, conn, creatorStmt); + } + + return (ResultSetImpl) Util.handleNewInstance(JDBC_4_RS_4_ARG_CTOR, + new Object[] { Long.valueOf(updateCount), Long.valueOf(updateID), conn, + creatorStmt}, conn.getExceptionInterceptor()); + } + + /** + * Creates a result set instance that represents a query result -- We need + * to provide factory-style methods so we can support both JDBC3 (and older) + * and JDBC4 runtimes, otherwise the class verifier complains when it tries + * to load JDBC4-only interface classes that are present in JDBC4 method + * signatures. + */ + + protected static ResultSetImpl getInstance(String catalog, Field[] fields, + RowData tuples, MySQLConnection conn, StatementImpl creatorStmt, + boolean isUpdatable) throws SQLException { + if (!Util.isJdbc4()) { + if (!isUpdatable) { + return new ResultSetImpl(catalog, fields, tuples, conn, creatorStmt); + } + + return new UpdatableResultSet(catalog, fields, tuples, conn, + creatorStmt); + } + + if (!isUpdatable) { + return (ResultSetImpl) Util + .handleNewInstance(JDBC_4_RS_6_ARG_CTOR, new Object[] { + catalog, fields, tuples, conn, creatorStmt }, conn.getExceptionInterceptor()); + } + + return (ResultSetImpl) Util.handleNewInstance(JDBC_4_UPD_RS_6_ARG_CTOR, + new Object[] { catalog, fields, tuples, conn, creatorStmt }, conn.getExceptionInterceptor()); + } + + /** + * Create a result set for an executeUpdate statement. + * + * @param updateCount + * the number of rows affected by the update + * @param updateID + * the autoincrement value (if any) + * @param conn + * DOCUMENT ME! + * @param creatorStmt + * DOCUMENT ME! + */ + public ResultSetImpl(long updateCount, long updateID, MySQLConnection conn, + StatementImpl creatorStmt) { + this.updateCount = updateCount; + this.updateId = updateID; + this.reallyResult = false; + this.fields = new Field[0]; + + this.connection = conn; + this.owningStatement = creatorStmt; + + this.retainOwningStatement = false; + + if (this.connection != null) { + this.exceptionInterceptor = this.connection.getExceptionInterceptor(); + + this.retainOwningStatement = + this.connection.getRetainStatementAfterResultSetClose(); + + this.connectionId = this.connection.getId(); + this.serverTimeZoneTz = this.connection.getServerTimezoneTZ(); + this.padCharsWithSpace = this.connection.getPadCharsWithSpace(); + + useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode(); + } + } + + /** + * Creates a new ResultSet object. + * + * @param catalog + * the database in use when we were created + * @param fields + * an array of Field objects (basically, the ResultSet MetaData) + * @param tuples + * actual row data + * @param conn + * the Connection that created us. + * @param creatorStmt + * DOCUMENT ME! + * + * @throws SQLException + * if an error occurs + */ + public ResultSetImpl(String catalog, Field[] fields, RowData tuples, + MySQLConnection conn, StatementImpl creatorStmt) throws SQLException { + this.connection = conn; + + this.retainOwningStatement = false; + + if (this.connection != null) { + this.exceptionInterceptor = this.connection.getExceptionInterceptor(); + this.useStrictFloatingPoint = this.connection + .getStrictFloatingPoint(); + this.setDefaultTimeZone(this.connection.getDefaultTimeZone()); + this.connectionId = this.connection.getId(); + this.useFastDateParsing = this.connection.getUseFastDateParsing(); + this.profileSql = this.connection.getProfileSql(); + this.retainOwningStatement = + this.connection.getRetainStatementAfterResultSetClose(); + this.jdbcCompliantTruncationForReads = this.connection.getJdbcCompliantTruncationForReads(); + this.useFastIntParsing = this.connection.getUseFastIntParsing(); + this.serverTimeZoneTz = this.connection.getServerTimezoneTZ(); + this.padCharsWithSpace = this.connection.getPadCharsWithSpace(); + } + + this.owningStatement = creatorStmt; + + this.catalog = catalog; + + this.fields = fields; + this.rowData = tuples; + this.updateCount = this.rowData.size(); + + if (Driver.DEBUG) { + System.out.println(Messages.getString("ResultSet.Retrieved__1") + + this.updateCount + " rows"); //$NON-NLS-1$ + } + + this.reallyResult = true; + + // Check for no results + if (this.rowData.size() > 0) { + if (this.updateCount == 1) { + if (this.thisRow == null) { + this.rowData.close(); // empty result set + this.updateCount = -1; + } + } + } else { + this.thisRow = null; + } + + this.rowData.setOwner(this); + + if (this.fields != null) { + initializeWithMetadata(); + } // else called by Connection.initializeResultsMetadataFromCache() when cached + useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode(); + + this.useColumnNamesInFindColumn = this.connection.getUseColumnNamesInFindColumn(); + + setRowPositionValidity(); + } + + public void initializeWithMetadata() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.rowData.setMetadata(this.fields); + + this.columnToIndexCache = new HashMap(); + + if (this.profileSql || this.connection.getUseUsageAdvisor()) { + this.columnUsed = new boolean[this.fields.length]; + this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable()); + this.resultId = resultCounter++; + this.useUsageAdvisor = this.connection.getUseUsageAdvisor(); + this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); + } + + if (this.connection.getGatherPerformanceMetrics()) { + this.connection.incrementNumberOfResultSetsCreated(); + + Set tableNamesSet = new HashSet(); + + for (int i = 0; i < this.fields.length; i++) { + Field f = this.fields[i]; + + String tableName = f.getOriginalTableName(); + + if (tableName == null) { + tableName = f.getTableName(); + } + + if (tableName != null) { + if (this.connection.lowerCaseTableNames()) { + tableName = tableName.toLowerCase(); // on windows, table + // names are not case-sens. + } + + tableNamesSet.add(tableName); + } + } + + this.connection.reportNumberOfTablesAccessed(tableNamesSet.size()); + } + } + } + + private synchronized void createCalendarIfNeeded() { + if (this.fastDateCal == null) { + this.fastDateCal = new GregorianCalendar(Locale.US); + this.fastDateCal.setTimeZone(this.getDefaultTimeZone()); + } + } + + /** + * JDBC 2.0 + * + *

+ * Move to an absolute row number in the result set. + *

+ * + *

+ * If row is positive, moves to an absolute row with respect to the + * beginning of the result set. The first row is row 1, the second is row 2, + * etc. + *

+ * + *

+ * If row is negative, moves to an absolute row position with respect to the + * end of result set. For example, calling absolute(-1) positions the cursor + * on the last row, absolute(-2) indicates the next-to-last row, etc. + *

+ * + *

+ * An attempt to position the cursor beyond the first/last row in the result + * set, leaves the cursor before/after the first/last row, respectively. + *

+ * + *

+ * Note: Calling absolute(1) is the same as calling first(). Calling + * absolute(-1) is the same as calling last(). + *

+ * + * @param row + * the row number to move to + * + * @return true if on the result set, false if off. + * + * @exception SQLException + * if a database-access error occurs, or row is 0, or result + * set type is TYPE_FORWARD_ONLY. + */ + public boolean absolute(int row) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + boolean b; + + if (this.rowData.size() == 0) { + b = false; + } else { + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + if (row == 0) { + beforeFirst(); + b = false; + } else if (row == 1) { + b = first(); + } else if (row == -1) { + b = last(); + } else if (row > this.rowData.size()) { + afterLast(); + b = false; + } else { + if (row < 0) { + // adjust to reflect after end of result set + int newRowPosition = this.rowData.size() + row + 1; + + if (newRowPosition <= 0) { + beforeFirst(); + b = false; + } else { + b = absolute(newRowPosition); + } + } else { + row--; // adjust for index difference + this.rowData.setCurrentRow(row); + this.thisRow = this.rowData.getAt(row); + b = true; + } + } + } + + setRowPositionValidity(); + + return b; + } + } + + /** + * JDBC 2.0 + * + *

+ * Moves to the end of the result set, just after the last row. Has no + * effect if the result set contains no rows. + *

+ * + * @exception SQLException + * if a database-access error occurs, or result set type is + * TYPE_FORWARD_ONLY. + */ + public void afterLast() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + if (this.rowData.size() != 0) { + this.rowData.afterLast(); + this.thisRow = null; + } + + setRowPositionValidity(); + } + } + + /** + * JDBC 2.0 + * + *

+ * Moves to the front of the result set, just before the first row. Has no + * effect if the result set contains no rows. + *

+ * + * @exception SQLException + * if a database-access error occurs, or result set type is + * TYPE_FORWARD_ONLY + */ + public void beforeFirst() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + if (this.rowData.size() == 0) { + return; + } + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + this.rowData.beforeFirst(); + this.thisRow = null; + + setRowPositionValidity(); + } + } + + // --------------------------------------------------------------------- + // Traversal/Positioning + // --------------------------------------------------------------------- + + /** + * Builds a hash between column names and their indices for fast retrieval. + */ + public void buildIndexMapping() throws SQLException { + int numFields = this.fields.length; + this.columnLabelToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER); + this.fullColumnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER); + this.columnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER); + + // We do this in reverse order, so that the 'first' column + // with a given name ends up as the final mapping in the + // hashtable... + // + // Quoting the JDBC Spec: + // + // "Column names used as input to getter + // methods are case insensitive. When a getter method is called with a + // column + // name and several columns have the same name, the value of the first + // matching column will be returned. " + // + for (int i = numFields - 1; i >= 0; i--) { + Integer index = Integer.valueOf(i); + String columnName = this.fields[i].getOriginalName(); + String columnLabel = this.fields[i].getName(); + String fullColumnName = this.fields[i].getFullName(); + + if (columnLabel != null) { + this.columnLabelToIndex.put(columnLabel, index); + } + + if (fullColumnName != null) { + this.fullColumnNameToIndex.put(fullColumnName, index); + } + + if (columnName != null) { + this.columnNameToIndex.put(columnName, index); + } + } + + // set the flag to prevent rebuilding... + this.hasBuiltIndexMapping = true; + } + + /** + * JDBC 2.0 The cancelRowUpdates() method may be called after calling an + * updateXXX() method(s) and before calling updateRow() to rollback the + * updates made to a row. If no updates have been made or updateRow() has + * already been called, then this method has no effect. + * + * @exception SQLException + * if a database-access error occurs, or if called when on + * the insert row. + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void cancelRowUpdates() throws SQLException { + throw new NotUpdatable(); + } + + /** + * Ensures that the result set is not closed + * + * @throws SQLException + * if the result set is closed + */ + protected final MySQLConnection checkClosed() throws SQLException { + MySQLConnection c = this.connection; + + if (c == null) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + + return c; + } + + /** + * Checks if columnIndex is within the number of columns in this result set. + * + * @param columnIndex + * the index to check + * + * @throws SQLException + * if the index is out of bounds + */ + protected final void checkColumnBounds(int columnIndex) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if ((columnIndex < 1)) { + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Column_Index_out_of_range_low", new Object[] { + Integer.valueOf(columnIndex), + Integer.valueOf(this.fields.length) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } else if ((columnIndex > this.fields.length)) { + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Column_Index_out_of_range_high", new Object[] { + Integer.valueOf(columnIndex), + Integer.valueOf(this.fields.length) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + if (this.profileSql || this.useUsageAdvisor) { + this.columnUsed[columnIndex - 1] = true; + } + } + } + + /** + * Ensures that the cursor is positioned on a valid row and that the result + * set is not closed + * + * @throws SQLException + * if the result set is not in a valid state for traversal + */ + protected void checkRowPos() throws SQLException { + checkClosed(); + + if (!this.onValidRow) { + throw SQLError.createSQLException(this.invalidRowReason, + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + } + + private boolean onValidRow = false; + private String invalidRowReason = null; + protected boolean useLegacyDatetimeCode; + private TimeZone serverTimeZoneTz; + + private void setRowPositionValidity() throws SQLException { + if (!this.rowData.isDynamic() && (this.rowData.size() == 0)) { + this.invalidRowReason = Messages + .getString("ResultSet.Illegal_operation_on_empty_result_set");//$NON-NLS-1$ + this.onValidRow = false; + } else if (this.rowData.isBeforeFirst()) { + this.invalidRowReason = Messages + .getString("ResultSet.Before_start_of_result_set_146"); //$NON-NLS-1$ + this.onValidRow = false; + } else if (this.rowData.isAfterLast()) { + this.invalidRowReason = Messages + .getString("ResultSet.After_end_of_result_set_148"); //$NON-NLS-1$ + this.onValidRow = false; + } else { + this.onValidRow = true; + this.invalidRowReason = null; + } + } + + /** + * We can't do this ourselves, otherwise the contract for + * Statement.getMoreResults() won't work correctly. + */ + public synchronized void clearNextResult() { + this.nextResultSet = null; + } + + /** + * After this call, getWarnings returns null until a new warning is reported + * for this ResultSet + * + * @exception SQLException + * if a database access error occurs + */ + public void clearWarnings() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.warningChain = null; + } + } + + /** + * In some cases, it is desirable to immediately release a ResultSet + * database and JDBC resources instead of waiting for this to happen when it + * is automatically closed. The close method provides this immediate + * release. + * + *

+ * Note: A ResultSet is automatically closed by the Statement the + * Statement that generated it when that Statement is closed, re-executed, + * or is used to retrieve the next result from a sequence of multiple + * results. A ResultSet is also automatically closed when it is garbage + * collected. + *

+ * + * @exception SQLException + * if a database access error occurs + */ + public void close() throws SQLException { + realClose(true); + } + + /** + * @return + */ + private int convertToZeroWithEmptyCheck() throws SQLException { + if (this.connection.getEmptyStringsConvertToZero()) { + return 0; + } + + throw SQLError.createSQLException("Can't convert empty string ('') to numeric", + SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST, getExceptionInterceptor()); + } + + private String convertToZeroLiteralStringWithEmptyCheck() + throws SQLException { + + if (this.connection.getEmptyStringsConvertToZero()) { + return "0"; + } + + throw SQLError.createSQLException("Can't convert empty string ('') to numeric", + SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST, getExceptionInterceptor()); + } + + // + // Note, row data is linked between these two result sets + // + public ResultSetInternalMethods copy() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + ResultSetInternalMethods rs = ResultSetImpl.getInstance(this.catalog, this.fields, this.rowData, + this.connection, this.owningStatement, false); // note, doesn't work for updatable result sets + + return rs; + } + } + + public void redefineFieldsForDBMD(Field[] f) { + this.fields = f; + + for (int i = 0; i < this.fields.length; i++) { + this.fields[i].setUseOldNameMetadata(true); + this.fields[i].setConnection(this.connection); + } + } + + public void populateCachedMetaData(CachedResultSetMetaData cachedMetaData) + throws SQLException { + cachedMetaData.fields = this.fields; + cachedMetaData.columnNameToIndex = this.columnLabelToIndex; + cachedMetaData.fullColumnNameToIndex = this.fullColumnNameToIndex; + cachedMetaData.metadata = getMetaData(); + } + + public void initializeFromCachedMetaData(CachedResultSetMetaData cachedMetaData) { + this.fields = cachedMetaData.fields; + this.columnLabelToIndex = cachedMetaData.columnNameToIndex; + this.fullColumnNameToIndex = cachedMetaData.fullColumnNameToIndex; + this.hasBuiltIndexMapping = true; + } + + + /** + * JDBC 2.0 Delete the current row from the result set and the underlying + * database. Cannot be called when on the insert row. + * + * @exception SQLException + * if a database-access error occurs, or if called when on + * the insert row. + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void deleteRow() throws SQLException { + throw new NotUpdatable(); + } + + /** + * @param columnIndex + * @param stringVal + * @param mysqlType + * @return + * @throws SQLException + */ + private String extractStringFromNativeColumn(int columnIndex, int mysqlType) + throws SQLException { + int columnIndexMinusOne = columnIndex - 1; + + this.wasNullFlag = false; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + String encoding = this.fields[columnIndexMinusOne] + .getCharacterSet(); + + return this.thisRow.getString(columnIndex - 1, encoding, this.connection); + } + + protected Date fastDateCreate(Calendar cal, int year, int month, + int day) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.useLegacyDatetimeCode) { + return TimeUtil.fastDateCreate(year, month, day, cal); + } + + if (cal == null) { + createCalendarIfNeeded(); + cal = this.fastDateCal; + } + + boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes(); + + return TimeUtil.fastDateCreate(useGmtMillis, + useGmtMillis ? getGmtCalendar() : cal, + cal, year, month, day); + } + } + + protected Time fastTimeCreate(Calendar cal, int hour, + int minute, int second) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (!this.useLegacyDatetimeCode) { + return TimeUtil.fastTimeCreate(hour, minute, second, cal, getExceptionInterceptor()); + } + + if (cal == null) { + createCalendarIfNeeded(); + cal = this.fastDateCal; + } + + return TimeUtil.fastTimeCreate(cal, hour, minute, second, getExceptionInterceptor()); + } + } + + protected Timestamp fastTimestampCreate(Calendar cal, int year, + int month, int day, int hour, int minute, int seconds, + int secondsPart) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (!this.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(cal.getTimeZone(), year, month, day, hour, + minute, seconds, secondsPart); + } + + if (cal == null) { + createCalendarIfNeeded(); + cal = this.fastDateCal; + } + + boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes(); + + return TimeUtil.fastTimestampCreate(useGmtMillis, + useGmtMillis ? getGmtCalendar() : null, + cal, year, month, day, hour, + minute, seconds, secondsPart); + } + } + + /* + /** + * Required by JDBC spec + */ + /* + protected void finalize() throws Throwable { + if (!this.isClosed) { + realClose(false); + } + } + */ + + // --------------------------JDBC 2.0----------------------------------- + // --------------------------------------------------------------------- + // Getter's and Setter's + // --------------------------------------------------------------------- + + + /* + * [For JDBC-3.0 and older - http://java.sun.com/j2se/1.5.0/docs/api/java/sql/ResultSet.html#findColumn(java.lang.String)] + * Map a ResultSet column name to a ResultSet column index + * + * @param columnName + * the name of the column + * + * @return the column index + * + * @exception SQLException + * if a database access error occurs + * + * [For JDBC-4.0 and newer - http://java.sun.com/javase/6/docs/api/java/sql/ResultSet.html#findColumn(java.lang.String)] + * + * Maps the given ResultSet column label to its ResultSet column index. + * + * @param columnLabel + * the label for the column specified with the SQL AS clause. If the + * SQL AS clause was not specified, then the label is the name of the column + * + * @return the column index of the given column name + */ + public int findColumn(String columnName) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + Integer index; + + if (!this.hasBuiltIndexMapping) { + buildIndexMapping(); + } + + index = this.columnToIndexCache.get(columnName); + + if (index != null) { + return index.intValue() + 1; + } + + index = this.columnLabelToIndex.get(columnName); + + if (index == null && this.useColumnNamesInFindColumn) { + index = this.columnNameToIndex.get(columnName); + } + + if (index == null) { + index = this.fullColumnNameToIndex.get(columnName); + } + + if (index != null) { + this.columnToIndexCache.put(columnName, index); + + return index.intValue() + 1; + } + + // Try this inefficient way, now + + for (int i = 0; i < this.fields.length; i++) { + if (this.fields[i].getName().equalsIgnoreCase(columnName)) { + return i + 1; + } else if (this.fields[i].getFullName() + .equalsIgnoreCase(columnName)) { + return i + 1; + } + } + + throw SQLError.createSQLException(Messages.getString("ResultSet.Column____112") + + columnName + + Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$ + SQLError.SQL_STATE_COLUMN_NOT_FOUND, getExceptionInterceptor()); + } + } + + /** + * JDBC 2.0 + * + *

+ * Moves to the first row in the result set. + *

+ * + * @return true if on a valid row, false if no rows in the result set. + * + * @exception SQLException + * if a database-access error occurs, or result set type is + * TYPE_FORWARD_ONLY. + */ + public boolean first() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + boolean b = true; + + if (this.rowData.isEmpty()) { + b = false; + } else { + + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + this.rowData.beforeFirst(); + this.thisRow = this.rowData.next(); + } + + setRowPositionValidity(); + + return b; + } + } + + /** + * JDBC 2.0 Get an array column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing an SQL array + * + * @throws SQLException + * if a database error occurs + * @throws NotImplemented + * DOCUMENT ME! + */ + public java.sql.Array getArray(int i) throws SQLException { + checkColumnBounds(i); + + throw SQLError.notImplemented(); + } + + /** + * JDBC 2.0 Get an array column. + * + * @param colName + * the column name + * + * @return an object representing an SQL array + * + * @throws SQLException + * if a database error occurs + * @throws NotImplemented + * DOCUMENT ME! + */ + public java.sql.Array getArray(String colName) throws SQLException { + return getArray(findColumn(colName)); + } + + /** + * A column value can be retrieved as a stream of ASCII characters and then + * read in chunks from the stream. This method is particulary suitable for + * retrieving large LONGVARCHAR values. The JDBC driver will do any + * necessary conversion from the database format into ASCII. + * + *

+ * Note: All the data in the returned stream must be read prior to + * getting the value of any other column. The next call to a get method + * implicitly closes the stream. Also, a stream may return 0 for available() + * whether there is data available or not. + *

+ * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return a Java InputStream that delivers the database column value as a + * stream of one byte ASCII characters. If the value is SQL NULL + * then the result is null + * + * @exception SQLException + * if a database access error occurs + * + * @see getBinaryStream + */ + public InputStream getAsciiStream(int columnIndex) throws SQLException { + checkRowPos(); + + if (!this.isBinaryEncoded) { + return getBinaryStream(columnIndex); + } + + return getNativeBinaryStream(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public InputStream getAsciiStream(String columnName) throws SQLException { + return getAsciiStream(findColumn(columnName)); + } + + /** + * JDBC 2.0 Get the value of a column in the current row as a + * java.math.BigDecimal object. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return the column value (full precision); if the value is SQL NULL, the + * result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + String stringVal = getString(columnIndex); + BigDecimal val; + + if (stringVal != null) { + if (stringVal.length() == 0) { + + val = new BigDecimal( + convertToZeroLiteralStringWithEmptyCheck()); + + return val; + } + + try { + val = new BigDecimal(stringVal); + + return val; + } catch (NumberFormatException ex) { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] { stringVal, + Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + return null; + } + + return getNativeBigDecimal(columnIndex); + } + + /** + * Get the value of a column in the current row as a java.math.BigDecimal + * object + * + * @param columnIndex + * the first column is 1, the second is 2... + * @param scale + * the number of digits to the right of the decimal + * + * @return the column value; if the value is SQL NULL, null + * + * @exception SQLException + * if a database access error occurs + * + * @deprecated + */ + public BigDecimal getBigDecimal(int columnIndex, int scale) + throws SQLException { + if (!this.isBinaryEncoded) { + String stringVal = getString(columnIndex); + BigDecimal val; + + if (stringVal != null) { + if (stringVal.length() == 0) { + val = new BigDecimal( + convertToZeroLiteralStringWithEmptyCheck()); + + try { + return val.setScale(scale); + } catch (ArithmeticException ex) { + try { + return val + .setScale(scale, BigDecimal.ROUND_HALF_UP); + } catch (ArithmeticException arEx) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Bad_format_for_BigDecimal", //$NON-NLS-1$ + new Object[] {stringVal, Integer.valueOf(columnIndex)}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + } + + try { + val = new BigDecimal(stringVal); + } catch (NumberFormatException ex) { + if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex); + + val = new BigDecimal(valueAsLong); + } else { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] { Integer.valueOf(columnIndex), + stringVal }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + try { + return val.setScale(scale); + } catch (ArithmeticException ex) { + try { + return val.setScale(scale, BigDecimal.ROUND_HALF_UP); + } catch (ArithmeticException arithEx) { + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_BigDecimal", + new Object[] { Integer.valueOf(columnIndex), + stringVal }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + } + + return null; + } + + return getNativeBigDecimal(columnIndex, scale); + } + + /** + * JDBC 2.0 Get the value of a column in the current row as a + * java.math.BigDecimal object. + * + * @param columnName + * the name of the column to retrieve the value from + * + * @return the BigDecimal value in the column + * + * @throws SQLException + * if an error occurs + */ + public BigDecimal getBigDecimal(String columnName) throws SQLException { + return getBigDecimal(findColumn(columnName)); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * @param scale + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + * + * @deprecated + */ + public BigDecimal getBigDecimal(String columnName, int scale) + throws SQLException { + return getBigDecimal(findColumn(columnName), scale); + } + + private final BigDecimal getBigDecimalFromString(String stringVal, + int columnIndex, int scale) throws SQLException { + BigDecimal bdVal; + + if (stringVal != null) { + if (stringVal.length() == 0) { + bdVal = new BigDecimal(convertToZeroLiteralStringWithEmptyCheck()); + + try { + return bdVal.setScale(scale); + } catch (ArithmeticException ex) { + try { + return bdVal.setScale(scale, BigDecimal.ROUND_HALF_UP); + } catch (ArithmeticException arEx) { + throw new SQLException(Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] { stringVal, + Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + } + } + } + + try { + try { + return new BigDecimal(stringVal).setScale(scale); + } catch (ArithmeticException ex) { + try { + return new BigDecimal(stringVal).setScale(scale, + BigDecimal.ROUND_HALF_UP); + } catch (ArithmeticException arEx) { + throw new SQLException(Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] { stringVal, + Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + } + } + } catch (NumberFormatException ex) { + if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex); + + try { + return new BigDecimal(valueAsLong).setScale(scale); + } catch (ArithmeticException arEx1) { + try { + return new BigDecimal(valueAsLong).setScale(scale, + BigDecimal.ROUND_HALF_UP); + } catch (ArithmeticException arEx2) { + throw new SQLException(Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] { stringVal, + Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + } + } + } + + if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TINY && + this.connection.getTinyInt1isBit() && this.fields[columnIndex - 1].getLength() == 1) { + return new BigDecimal(stringVal.equalsIgnoreCase("true") ? 1 : 0).setScale(scale); + } + + throw new SQLException(Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] { stringVal, + Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + } + } + + return null; + } + + /** + * A column value can also be retrieved as a binary stream. This method is + * suitable for retrieving LONGVARBINARY values. + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return a Java InputStream that delivers the database column value as a + * stream of bytes. If the value is SQL NULL, then the result is + * null + * + * @exception SQLException + * if a database access error occurs + * + * @see getAsciiStream + * @see getUnicodeStream + */ + public InputStream getBinaryStream(int columnIndex) throws SQLException { + checkRowPos(); + + if (!this.isBinaryEncoded) { + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return this.thisRow.getBinaryInputStream(columnIndexMinusOne); + } + + return getNativeBinaryStream(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public InputStream getBinaryStream(String columnName) throws SQLException { + return getBinaryStream(findColumn(columnName)); + } + + /** + * JDBC 2.0 Get a BLOB column. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return an object representing a BLOB + * + * @throws SQLException + * if an error occurs. + */ + public java.sql.Blob getBlob(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + checkRowPos(); + + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return null; + } + + if (!this.connection.getEmulateLocators()) { + return new Blob(this.thisRow.getColumnValue(columnIndexMinusOne), getExceptionInterceptor()); + } + + return new BlobFromLocator(this, columnIndex, getExceptionInterceptor()); + } + + return getNativeBlob(columnIndex); + } + + /** + * JDBC 2.0 Get a BLOB column. + * + * @param colName + * the column name + * + * @return an object representing a BLOB + * + * @throws SQLException + * if an error occurs. + */ + public java.sql.Blob getBlob(String colName) throws SQLException { + return getBlob(findColumn(colName)); + } + + /** + * Get the value of a column in the current row as a Java boolean + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value, false for SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public boolean getBoolean(int columnIndex) throws SQLException { + + checkColumnBounds(columnIndex); + + // + // MySQL 5.0 and newer have an actual BIT type, + // so we need to check for that here... + // + + int columnIndexMinusOne = columnIndex - 1; + + Field field = this.fields[columnIndexMinusOne]; + + if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + return byteArrayToBoolean(columnIndexMinusOne); + } + + this.wasNullFlag = false; + + int sqlType = field.getSQLType(); + + switch (sqlType) { + case Types.BOOLEAN: + if (field.getMysqlType() == -1) { // from dbmd + String stringVal = getString(columnIndex); + + return getBooleanFromString(stringVal); + } + + long boolVal = getLong(columnIndex, false); + + return (boolVal == -1 || boolVal > 0); + case Types.BIT: + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.DECIMAL: + case Types.NUMERIC: + case Types.REAL: + case Types.FLOAT: + case Types.DOUBLE: + boolVal = getLong(columnIndex, false); + + return (boolVal == -1 || boolVal > 0); + default: + if (this.connection.getPedantic()) { + // Table B-6 from JDBC spec + switch (sqlType) { + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + case Types.DATE: + case Types.TIME: + case Types.TIMESTAMP: + case Types.CLOB: + case Types.BLOB: + case Types.ARRAY: + case Types.REF: + case Types.DATALINK: + case Types.STRUCT: + case Types.JAVA_OBJECT: + throw SQLError.createSQLException("Required type conversion not allowed", + SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST, getExceptionInterceptor()); + } + } + + if (sqlType == Types.BINARY || + sqlType == Types.VARBINARY || + sqlType == Types.LONGVARBINARY || + sqlType == Types.BLOB) { + return byteArrayToBoolean(columnIndexMinusOne); + } + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getBoolean()", columnIndex, + this.thisRow.getColumnValue(columnIndexMinusOne), this.fields[columnIndex], + new int[] { + MysqlDefs.FIELD_TYPE_BIT, + MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + String stringVal = getString(columnIndex); + + return getBooleanFromString(stringVal); + } + } + + private boolean byteArrayToBoolean(int columnIndexMinusOne) throws SQLException { + Object value = this.thisRow.getColumnValue(columnIndexMinusOne); + + if (value == null) { + this.wasNullFlag = true; + + return false; + } + + this.wasNullFlag = false; + + if (((byte[]) value).length == 0) { + return false; + } + + byte boolVal = ((byte[]) value)[0]; + + if (boolVal == (byte)'1') { + return true; + } else if (boolVal == (byte)'0') { + return false; + } + + return (boolVal == -1 || boolVal > 0); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public boolean getBoolean(String columnName) throws SQLException { + return getBoolean(findColumn(columnName)); + } + + private final boolean getBooleanFromString(String stringVal) + throws SQLException { + if ((stringVal != null) && (stringVal.length() > 0)) { + int c = Character.toLowerCase(stringVal.charAt(0)); + + return ((c == 't') || (c == 'y') || (c == '1') || stringVal + .equals("-1")); + } + + return false; + } + + /** + * Get the value of a column in the current row as a Java byte. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public byte getByte(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + String stringVal = getString(columnIndex); + + if (this.wasNullFlag || (stringVal == null)) { + return 0; + } + + return getByteFromString(stringVal, columnIndex); + } + + return getNativeByte(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public byte getByte(String columnName) throws SQLException { + return getByte(findColumn(columnName)); + } + + private final byte getByteFromString(String stringVal, int columnIndex) + throws SQLException { + + if (stringVal != null && stringVal.length() == 0) { + return (byte) convertToZeroWithEmptyCheck(); + } + + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + if (stringVal == null) { + return 0; + } + + stringVal = stringVal.trim(); + + try { + int decimalIndex = stringVal.indexOf("."); + + + if (decimalIndex != -1) { + double valueAsDouble = Double.parseDouble(stringVal); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Byte.MIN_VALUE + || valueAsDouble > Byte.MAX_VALUE) { + throwRangeException(stringVal, columnIndex, + Types.TINYINT); + } + } + + return (byte) valueAsDouble; + } + + long valueAsLong = Long.parseLong(stringVal); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsLong < Byte.MIN_VALUE + || valueAsLong > Byte.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex, Types.TINYINT); + } + } + + return (byte) valueAsLong; + } catch (NumberFormatException NFE) { + throw SQLError.createSQLException( + Messages.getString("ResultSet.Value____173") + + stringVal //$NON-NLS-1$ + + Messages + .getString("ResultSet.___is_out_of_range_[-127,127]_174"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * Get the value of a column in the current row as a Java byte array. + * + *

+ * Be warned If the blob is huge, then you may run out of memory. + *

+ * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database access error occurs + */ + public byte[] getBytes(int columnIndex) throws SQLException { + return getBytes(columnIndex, false); + } + + protected byte[] getBytes(int columnIndex, boolean noConversion) + throws SQLException { + if (!this.isBinaryEncoded) { + checkRowPos(); + + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return null; + } + + return this.thisRow.getColumnValue(columnIndexMinusOne); + } + + return getNativeBytes(columnIndex, noConversion); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public byte[] getBytes(String columnName) throws SQLException { + return getBytes(findColumn(columnName)); + } + + private final byte[] getBytesFromString(String stringVal) + throws SQLException { + if (stringVal != null) { + return StringUtils.getBytes(stringVal, this.connection + .getEncoding(), this.connection + .getServerCharacterEncoding(), this.connection + .parserKnowsUnicode(), + this.connection, getExceptionInterceptor()); + } + + return null; + } + + public int getBytesSize() throws SQLException { + RowData localRowData = this.rowData; + + checkClosed(); + + if (localRowData instanceof RowDataStatic) { + int bytesSize = 0; + + int numRows = localRowData.size(); + + for (int i = 0; i < numRows; i++) { + bytesSize += localRowData.getAt(i).getBytesSize(); + } + + return bytesSize; + } + + return -1; + } + + /** + * Optimization to only use one calendar per-session, or calculate it for + * each call, depending on user configuration + */ + protected Calendar getCalendarInstanceForSessionOrNew() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.connection != null) { + return this.connection.getCalendarInstanceForSessionOrNew(); + } + + // punt, no connection around + return new GregorianCalendar(); + } + } + + /** + * JDBC 2.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnIndex + * the column to get the value from + * + * @return the value in the column as a java.io.Reader. + * + * @throws SQLException + * if an error occurs + */ + public java.io.Reader getCharacterStream(int columnIndex) + throws SQLException { + if (!this.isBinaryEncoded) { + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return this.thisRow.getReader(columnIndexMinusOne); + } + + return getNativeCharacterStream(columnIndex); + } + + /** + * JDBC 2.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnName + * the column name to retrieve the value from + * + * @return the value as a java.io.Reader + * + * @throws SQLException + * if an error occurs + */ + public java.io.Reader getCharacterStream(String columnName) + throws SQLException { + return getCharacterStream(findColumn(columnName)); + } + + private final java.io.Reader getCharacterStreamFromString(String stringVal) + throws SQLException { + if (stringVal != null) { + return new StringReader(stringVal); + } + + return null; + } + + /** + * JDBC 2.0 Get a CLOB column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing a CLOB + * + * @throws SQLException + * if an error occurs + */ + public java.sql.Clob getClob(int i) throws SQLException { + if (!this.isBinaryEncoded) { + String asString = getStringForClob(i); + + if (asString == null) { + return null; + } + + return new com.mysql.jdbc.Clob(asString, getExceptionInterceptor()); + } + + return getNativeClob(i); + } + + /** + * JDBC 2.0 Get a CLOB column. + * + * @param colName + * the column name + * + * @return an object representing a CLOB + * + * @throws SQLException + * if an error occurs + */ + public java.sql.Clob getClob(String colName) throws SQLException { + return getClob(findColumn(colName)); + } + + private final java.sql.Clob getClobFromString(String stringVal) throws SQLException { + return new com.mysql.jdbc.Clob(stringVal, getExceptionInterceptor()); + } + + /** + * JDBC 2.0 Return the concurrency of this result set. The concurrency used + * is determined by the statement that created the result set. + * + * @return the concurrency type, CONCUR_READ_ONLY, etc. + * + * @throws SQLException + * if a database-access error occurs + */ + public int getConcurrency() throws SQLException { + return (CONCUR_READ_ONLY); + } + + /** + * Get the name of the SQL cursor used by this ResultSet + * + *

+ * In SQL, a result table is retrieved though a cursor that is named. The + * current row of a result can be updated or deleted using a positioned + * update/delete statement that references the cursor name. + *

+ * + *

+ * JDBC supports this SQL feature by providing the name of the SQL cursor + * used by a ResultSet. The current row of a ResulSet is also the current + * row of this SQL cursor. + *

+ * + *

+ * Note: If positioned update is not supported, a SQLException is + * thrown. + *

+ * + * @return the ResultSet's SQL cursor name. + * + * @exception SQLException + * if a database access error occurs + */ + public String getCursorName() throws SQLException { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Positioned_Update_not_supported"), + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); //$NON-NLS-1$ + } + + /** + * Get the value of a column in the current row as a java.sql.Date object + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value; null if SQL NULL + * + * @exception java.sql.SQLException + * if a database access error occurs + */ + public java.sql.Date getDate(int columnIndex) throws java.sql.SQLException { + return getDate(columnIndex, null); + } + + /** + * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date + * object. Use the calendar to construct an appropriate millisecond value + * for the Date, if the underlying database doesn't store timezone + * information. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param cal + * the calendar to use in constructing the date + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Date getDate(int columnIndex, Calendar cal) + throws SQLException { + if (this.isBinaryEncoded) { + return getNativeDate(columnIndex, cal); + } + + if (!this.useFastDateParsing) { + String stringVal = getStringInternal(columnIndex, false); + + if (stringVal == null) { + return null; + } + + return getDateFromString(stringVal, columnIndex, cal); + } + + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + Date tmpDate = this.thisRow.getDateFast(columnIndexMinusOne, this.connection, this, cal); + if ((this.thisRow.isNull(columnIndexMinusOne)) + || (tmpDate == null)) { + + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return tmpDate; + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws java.sql.SQLException + * DOCUMENT ME! + */ + public java.sql.Date getDate(String columnName) + throws java.sql.SQLException { + return getDate(findColumn(columnName)); + } + + /** + * Get the value of a column in the current row as a java.sql.Date object. + * Use the calendar to construct an appropriate millisecond value for the + * Date, if the underlying database doesn't store timezone information. + * + * @param columnName + * is the SQL name of the column + * @param cal + * the calendar to use in constructing the date + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Date getDate(String columnName, Calendar cal) + throws SQLException { + return getDate(findColumn(columnName), cal); + } + + private final java.sql.Date getDateFromString(String stringVal, + int columnIndex, Calendar targetCalendar) throws SQLException { + int year = 0; + int month = 0; + int day = 0; + + try { + this.wasNullFlag = false; + + if (stringVal == null) { + this.wasNullFlag = true; + + return null; + } + + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + stringVal = stringVal.trim(); + + if (stringVal.equals("0") || stringVal.equals("0000-00-00") + || stringVal.equals("0000-00-00 00:00:00") + || stringVal.equals("00000000000000") + || stringVal.equals("0")) { + + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(this.connection.getZeroDateTimeBehavior())) { + this.wasNullFlag = true; + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(this.connection.getZeroDateTimeBehavior())) { + throw SQLError.createSQLException("Value '" + stringVal + + "' can not be represented as java.sql.Date", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + // We're left with the case of 'round' to a date Java _can_ + // represent, which is '0001-01-01'. + return fastDateCreate(targetCalendar, 1, 1, 1); + + } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) { + // Convert from TIMESTAMP + switch (stringVal.length()) { + case 21: + case 19: { // java.sql.Timestamp format + year = Integer.parseInt(stringVal.substring(0, 4)); + month = Integer.parseInt(stringVal.substring(5, 7)); + day = Integer.parseInt(stringVal.substring(8, 10)); + + return fastDateCreate(targetCalendar, year, month, day); + } + + case 14: + case 8: { + year = Integer.parseInt(stringVal.substring(0, 4)); + month = Integer.parseInt(stringVal.substring(4, 6)); + day = Integer.parseInt(stringVal.substring(6, 8)); + + return fastDateCreate(targetCalendar, year, month, day); + } + + case 12: + case 10: + case 6: { + year = Integer.parseInt(stringVal.substring(0, 2)); + + if (year <= 69) { + year = year + 100; + } + + month = Integer.parseInt(stringVal.substring(2, 4)); + day = Integer.parseInt(stringVal.substring(4, 6)); + + return fastDateCreate(targetCalendar, year + 1900, month, day); + } + + case 4: { + year = Integer.parseInt(stringVal.substring(0, 4)); + + if (year <= 69) { + year = year + 100; + } + + month = Integer.parseInt(stringVal.substring(2, 4)); + + return fastDateCreate(targetCalendar, year + 1900, month, 1); + } + + case 2: { + year = Integer.parseInt(stringVal.substring(0, 2)); + + if (year <= 69) { + year = year + 100; + } + + return fastDateCreate(targetCalendar, year + 1900, 1, 1); + } + + default: + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_Date", new Object[] { + stringVal, Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } /* endswitch */ + } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { + + if (stringVal.length() == 2 || stringVal.length() == 1) { + year = Integer.parseInt(stringVal); + + if (year <= 69) { + year = year + 100; + } + + year += 1900; + } else { + year = Integer.parseInt(stringVal.substring(0, 4)); + } + + return fastDateCreate(targetCalendar, year, 1, 1); + } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) { + return fastDateCreate(targetCalendar, 1970, 1, 1); // Return EPOCH + } else { + if (stringVal.length() < 10) { + if (stringVal.length() == 8) { + return fastDateCreate(targetCalendar, 1970, 1, 1); // Return EPOCH for TIME + } + + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_Date", new Object[] { + stringVal, Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + if (stringVal.length() != 18) { + year = Integer.parseInt(stringVal.substring(0, 4)); + month = Integer.parseInt(stringVal.substring(5, 7)); + day = Integer.parseInt(stringVal.substring(8, 10)); + } else { + // JDK-1.3 timestamp format, not real easy to parse positionally :p + StringTokenizer st = new StringTokenizer(stringVal, "- "); + + year = Integer.parseInt(st.nextToken()); + month = Integer.parseInt(st.nextToken()); + day = Integer.parseInt(st.nextToken()); + } + } + + return fastDateCreate(targetCalendar, year, month, day); + } catch (SQLException sqlEx) { + throw sqlEx; // don't re-wrap + } catch (Exception e) { + SQLException sqlEx = SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_Date", new Object[] { stringVal, + Integer.valueOf(columnIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + + sqlEx.initCause(e); + + throw sqlEx; + } + } + + private TimeZone getDefaultTimeZone() { + if (!this.useLegacyDatetimeCode && this.connection != null) { + return this.serverTimeZoneTz; + } + + return this.connection.getDefaultTimeZone(); + } + + /** + * Get the value of a column in the current row as a Java double. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public double getDouble(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + return getDoubleInternal(columnIndex); + } + + return getNativeDouble(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public double getDouble(String columnName) throws SQLException { + return getDouble(findColumn(columnName)); + } + + private final double getDoubleFromString(String stringVal, int columnIndex) + throws SQLException { + return getDoubleInternal(stringVal, columnIndex); + } + + /** + * Converts a string representation of a number to a double. Need a faster + * way to do this. + * + * @param colIndex + * the 1-based index of the column to retrieve a double from. + * + * @return the double value represented by the string in buf + * + * @throws SQLException + * if an error occurs + */ + protected double getDoubleInternal(int colIndex) throws SQLException { + return getDoubleInternal(getString(colIndex), colIndex); + } + + /** + * Converts a string representation of a number to a double. Need a faster + * way to do this. + * + * @param stringVal + * the double as a String + * @param colIndex + * the 1-based index of the column to retrieve a double from. + * + * @return the double value represented by the string in buf + * + * @throws SQLException + * if an error occurs + */ + protected double getDoubleInternal(String stringVal, int colIndex) + throws SQLException { + try { + if ((stringVal == null)) { + return 0; + } + + if (stringVal.length() == 0) { + return convertToZeroWithEmptyCheck(); + } + + double d = Double.parseDouble(stringVal); + + if (this.useStrictFloatingPoint) { + // Fix endpoint rounding precision loss in MySQL server + if (d == 2.147483648E9) { + // Fix Odd end-point rounding on MySQL + d = 2.147483647E9; + } else if (d == 1.0000000036275E-15) { + // Fix odd end-point rounding on MySQL + d = 1.0E-15; + } else if (d == 9.999999869911E14) { + d = 9.99999999999999E14; + } else if (d == 1.4012984643248E-45) { + d = 1.4E-45; + } else if (d == 1.4013E-45) { + d = 1.4E-45; + } else if (d == 3.4028234663853E37) { + d = 3.4028235E37; + } else if (d == -2.14748E9) { + d = -2.147483648E9; + } else if (d == 3.40282E37) { + d = 3.4028235E37; + } + } + + return d; + } catch (NumberFormatException e) { + if (this.fields[colIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(colIndex); + + return valueAsLong; + } + + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_number", new Object[] { + stringVal, Integer.valueOf(colIndex) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + /** + * JDBC 2.0 Returns the fetch direction for this result set. + * + * @return the fetch direction for this result set. + * + * @exception SQLException + * if a database-access error occurs + */ + public int getFetchDirection() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.fetchDirection; + } + } + + /** + * JDBC 2.0 Return the fetch size for this result set. + * + * @return the fetch size for this result set. + * + * @exception SQLException + * if a database-access error occurs + */ + public int getFetchSize() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.fetchSize; + } + } + + /** + * Returns the first character of the query that this result set was created + * from. + * + * @return the first character of the query...uppercased + */ + public char getFirstCharOfQuery() { + try { + synchronized (checkClosed().getConnectionMutex()) { + return this.firstCharOfQuery; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve interface + } + } + + /** + * Get the value of a column in the current row as a Java float. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public float getFloat(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + String val = null; + + val = getString(columnIndex); + + return getFloatFromString(val, columnIndex); + } + + return getNativeFloat(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public float getFloat(String columnName) throws SQLException { + return getFloat(findColumn(columnName)); + } + + private final float getFloatFromString(String val, int columnIndex) + throws SQLException { + try { + if ((val != null)) { + if (val.length() == 0) { + return convertToZeroWithEmptyCheck(); + } + + float f = Float.parseFloat(val); + + if (this.jdbcCompliantTruncationForReads) { + if (f == Float.MIN_VALUE || f == Float.MAX_VALUE) { + double valAsDouble = Double.parseDouble(val); + + // Straight comparison is not reliable when at + // absolute endpoints of Float.MIN_VALUE or + // Float.MAX_VALUE, so use epsillons with DOUBLEs + + if ((valAsDouble < Float.MIN_VALUE - MIN_DIFF_PREC) + || (valAsDouble > Float.MAX_VALUE - MAX_DIFF_PREC)) { + throwRangeException(String.valueOf(valAsDouble), columnIndex, + Types.FLOAT); + } + } + } + + return f; + } + + return 0; // for NULL + } catch (NumberFormatException nfe) { + try { + Double valueAsDouble = new Double(val); + float valueAsFloat = valueAsDouble.floatValue(); + + if (this.jdbcCompliantTruncationForReads) { + + if (this.jdbcCompliantTruncationForReads && + valueAsFloat == Float.NEGATIVE_INFINITY || + valueAsFloat == Float.POSITIVE_INFINITY) { + throwRangeException(valueAsDouble.toString(), + columnIndex, Types.FLOAT); + } + } + + return valueAsFloat; + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getFloat()_-____200") + + val //$NON-NLS-1$ + + Messages.getString("ResultSet.___in_column__201") + + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * Get the value of a column in the current row as a Java int. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public int getInt(int columnIndex) throws SQLException { + checkRowPos(); + + if (!this.isBinaryEncoded) { + int columnIndexMinusOne = columnIndex - 1; + if (this.useFastIntParsing) { + checkColumnBounds(columnIndex); + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return 0; + } + + if (this.thisRow.length(columnIndexMinusOne) == 0) { + return convertToZeroWithEmptyCheck(); + } + + boolean needsFullParse = this.thisRow + .isFloatingPointNumber(columnIndexMinusOne); + + if (!needsFullParse) { + try { + return getIntWithOverflowCheck(columnIndexMinusOne); + } catch (NumberFormatException nfe) { + try { + + return parseIntAsDouble(columnIndex, this.thisRow + .getString(columnIndexMinusOne, + this.fields[columnIndexMinusOne] + .getCharacterSet(), + this.connection)); + } catch (NumberFormatException newNfe) { + // ignore, it's not a number + } + + if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex); + + if (this.connection + .getJdbcCompliantTruncationForReads() + && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) { + throwRangeException( + String.valueOf(valueAsLong), + columnIndex, Types.INTEGER); + } + + return (int) valueAsLong; + } + + throw SQLError + .createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getInt()_-____74") + + this.thisRow + .getString( + columnIndexMinusOne, + this.fields[columnIndexMinusOne] + .getCharacterSet(), + this.connection) //$NON-NLS-1$ + + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + } + + String val = null; + + try { + val = getString(columnIndex); + + if ((val != null)) { + if (val.length() == 0) { + return convertToZeroWithEmptyCheck(); + } + + if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) + && (val.indexOf(".") == -1)) { + int intVal = Integer.parseInt(val); + + checkForIntegerTruncation(columnIndexMinusOne, null, intVal); + + return intVal; + } + + // Convert floating point + int intVal = parseIntAsDouble(columnIndex, val); + + checkForIntegerTruncation(columnIndex, null, intVal); + + return intVal; + } + + return 0; + } catch (NumberFormatException nfe) { + try { + return parseIntAsDouble(columnIndex, val); + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex); + + if (this.jdbcCompliantTruncationForReads + && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex, Types.INTEGER); + } + + return (int) valueAsLong; + } + + throw SQLError + .createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getInt()_-____74") + + val //$NON-NLS-1$ + + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return getNativeInt(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public int getInt(String columnName) throws SQLException { + return getInt(findColumn(columnName)); + } + + private final int getIntFromString(String val, int columnIndex) + throws SQLException { + try { + if ((val != null)) { + + if (val.length() == 0) { + return convertToZeroWithEmptyCheck(); + } + + if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) + && (val.indexOf(".") == -1)) { + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + val = val.trim(); + + int valueAsInt = Integer.parseInt(val); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsInt == Integer.MIN_VALUE + || valueAsInt == Integer.MAX_VALUE) { + long valueAsLong = Long.parseLong(val); + + if (valueAsLong < Integer.MIN_VALUE + || valueAsLong > Integer.MAX_VALUE) { + throwRangeException( + String.valueOf(valueAsLong), + columnIndex, Types.INTEGER); + } + } + } + + return valueAsInt; + } + + // Convert floating point + + double valueAsDouble = Double.parseDouble(val); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Integer.MIN_VALUE + || valueAsDouble > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex, Types.INTEGER); + } + } + + return (int) valueAsDouble; + } + + return 0; // for NULL + } catch (NumberFormatException nfe) { + try { + double valueAsDouble = Double.parseDouble(val); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Integer.MIN_VALUE + || valueAsDouble > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex, Types.INTEGER); + } + } + + return (int) valueAsDouble; + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + throw SQLError.createSQLException(Messages + .getString("ResultSet.Invalid_value_for_getInt()_-____206") + + val //$NON-NLS-1$ + + Messages.getString("ResultSet.___in_column__207") + + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * Get the value of a column in the current row as a Java long. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public long getLong(int columnIndex) throws SQLException { + return getLong(columnIndex, true); + } + + private long getLong(int columnIndex, boolean overflowCheck) throws SQLException { + if (!this.isBinaryEncoded) { + checkRowPos(); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.useFastIntParsing) { + + checkColumnBounds(columnIndex); + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return 0; + } + + if (this.thisRow.length(columnIndexMinusOne) == 0) { + return convertToZeroWithEmptyCheck(); + } + + boolean needsFullParse = this.thisRow.isFloatingPointNumber(columnIndexMinusOne); + + if (!needsFullParse) { + try { + return getLongWithOverflowCheck(columnIndexMinusOne, overflowCheck); + } catch (NumberFormatException nfe) { + try { + // To do: Warn of over/underflow??? + return parseLongAsDouble(columnIndexMinusOne, this.thisRow + .getString(columnIndexMinusOne, + this.fields[columnIndexMinusOne] + .getCharacterSet(), + this.connection)); + } catch (NumberFormatException newNfe) { + // ; // ignore, it's not a number + } + + if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + return getNumericRepresentationOfSQLBitType(columnIndex); + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getLong()_-____79") + + this.thisRow + .getString(columnIndexMinusOne, + this.fields[columnIndexMinusOne] + .getCharacterSet(), + this.connection) //$NON-NLS-1$ + + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + } + + String val = null; + + try { + val = getString(columnIndex); + + if ((val != null)) { + if (val.length() == 0) { + return convertToZeroWithEmptyCheck(); + } + + if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) { + return parseLongWithOverflowCheck(columnIndexMinusOne, null, + val, overflowCheck); + } + + // Convert floating point + return parseLongAsDouble(columnIndexMinusOne, val); + } + + return 0; // for NULL + } catch (NumberFormatException nfe) { + try { + return parseLongAsDouble(columnIndexMinusOne, val); + } catch (NumberFormatException newNfe) { + // ; // ignore, it's not a number + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getLong()_-____79") + + val //$NON-NLS-1$ + + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return getNativeLong(columnIndex, overflowCheck, true); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public long getLong(String columnName) throws SQLException { + return getLong(findColumn(columnName)); + } + + private final long getLongFromString(String val, int columnIndexZeroBased) + throws SQLException { + try { + if ((val != null)) { + + if (val.length() == 0) { + return convertToZeroWithEmptyCheck(); + } + + if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) { + return parseLongWithOverflowCheck(columnIndexZeroBased, null, val, true); + } + + // Convert floating point + return parseLongAsDouble(columnIndexZeroBased, val); + } + + return 0; // for NULL + } catch (NumberFormatException nfe) { + try { + // To do: Warn of over/underflow??? + return parseLongAsDouble(columnIndexZeroBased, val); + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getLong()_-____211") + + val //$NON-NLS-1$ + + Messages.getString("ResultSet.___in_column__212") + + (columnIndexZeroBased + 1), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * The numbers, types and properties of a ResultSet's columns are provided + * by the getMetaData method + * + * @return a description of the ResultSet's columns + * + * @exception SQLException + * if a database access error occurs + */ + public java.sql.ResultSetMetaData getMetaData() throws SQLException { + checkClosed(); + + return new com.mysql.jdbc.ResultSetMetaData(fields, connection.getUseOldAliasMetadataBehavior(), + connection.getYearIsDateType(), getExceptionInterceptor()); + } + + /** + * JDBC 2.0 Get an array column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing an SQL array + * + * @throws SQLException + * if a database error occurs + * @throws NotImplemented + * DOCUMENT ME! + */ + protected java.sql.Array getNativeArray(int i) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * A column value can be retrieved as a stream of ASCII characters and then + * read in chunks from the stream. This method is particulary suitable for + * retrieving large LONGVARCHAR values. The JDBC driver will do any + * necessary conversion from the database format into ASCII. + * + *

+ * Note: All the data in the returned stream must be read prior to + * getting the value of any other column. The next call to a get method + * implicitly closes the stream. Also, a stream may return 0 for available() + * whether there is data available or not. + *

+ * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return a Java InputStream that delivers the database column value as a + * stream of one byte ASCII characters. If the value is SQL NULL + * then the result is null + * + * @exception SQLException + * if a database access error occurs + * + * @see getBinaryStream + */ + protected InputStream getNativeAsciiStream(int columnIndex) + throws SQLException { + checkRowPos(); + + return getNativeBinaryStream(columnIndex); + } + + /** + * JDBC 2.0 Get the value of a column in the current row as a + * java.math.BigDecimal object. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return the column value (full precision); if the value is SQL NULL, the + * result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + protected BigDecimal getNativeBigDecimal(int columnIndex) + throws SQLException { + + checkColumnBounds(columnIndex); + + int scale = this.fields[columnIndex - 1].getDecimals(); + + return getNativeBigDecimal(columnIndex, scale); + } + + /** + * Get the value of a column in the current row as a java.math.BigDecimal + * object + * + * @param columnIndex + * the first column is 1, the second is 2... + * @param scale + * the number of digits to the right of the decimal + * + * @return the column value; if the value is SQL NULL, null + * + * @exception SQLException + * if a database access error occurs + */ + protected BigDecimal getNativeBigDecimal(int columnIndex, int scale) + throws SQLException { + checkColumnBounds(columnIndex); + + String stringVal = null; + + Field f = this.fields[columnIndex - 1]; + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (value == null) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + switch (f.getSQLType()) { + case Types.DECIMAL: + case Types.NUMERIC: + stringVal = StringUtils + .toAsciiString((byte[]) value); + break; + default: + stringVal = getNativeString(columnIndex); + } + + return getBigDecimalFromString(stringVal, columnIndex, scale); + } + + /** + * A column value can also be retrieved as a binary stream. This method is + * suitable for retrieving LONGVARBINARY values. + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return a Java InputStream that delivers the database column value as a + * stream of bytes. If the value is SQL NULL, then the result is + * null + * + * @exception SQLException + * if a database access error occurs + * + * @see getAsciiStream + * @see getUnicodeStream + */ + protected InputStream getNativeBinaryStream(int columnIndex) + throws SQLException { + checkRowPos(); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + switch (this.fields[columnIndexMinusOne].getSQLType()) { + case Types.BIT: + case Types.BINARY: + case Types.VARBINARY: + case Types.BLOB: + case Types.LONGVARBINARY: + return this.thisRow.getBinaryInputStream(columnIndexMinusOne); + } + + byte[] b = getNativeBytes(columnIndex, false); + + if (b != null) { + return new ByteArrayInputStream(b); + } + + return null; + } + + /** + * JDBC 2.0 Get a BLOB column. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return an object representing a BLOB + * + * @throws SQLException + * if an error occurs. + */ + protected java.sql.Blob getNativeBlob(int columnIndex) throws SQLException { + checkRowPos(); + + checkColumnBounds(columnIndex); + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (value == null) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return null; + } + + int mysqlType = this.fields[columnIndex - 1].getMysqlType(); + + byte[] dataAsBytes = null; + + switch (mysqlType) { + case MysqlDefs.FIELD_TYPE_TINY_BLOB: + case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: + case MysqlDefs.FIELD_TYPE_LONG_BLOB: + case MysqlDefs.FIELD_TYPE_BLOB: + dataAsBytes = (byte[]) value; + break; + + default: + dataAsBytes = getNativeBytes(columnIndex, false); + } + + if (!this.connection.getEmulateLocators()) { + return new Blob(dataAsBytes, getExceptionInterceptor()); + } + + return new BlobFromLocator(this, columnIndex, getExceptionInterceptor()); + } + + public static boolean arraysEqual(byte[] left, byte[] right) { + if (left == null) { + return right == null; + } + if (right == null) { + return false; + } + if (left.length != right.length) { + return false; + } + for (int i = 0; i < left.length; i++) { + if (left[i] != right[i]) { + return false; + } + } + return true; + } + + /** + * Get the value of a column in the current row as a Java byte. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected byte getNativeByte(int columnIndex) throws SQLException { + return getNativeByte(columnIndex, true); + } + + protected byte getNativeByte(int columnIndex, boolean overflowCheck) throws SQLException { + checkRowPos(); + + checkColumnBounds(columnIndex); + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (value == null) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + columnIndex--; + + Field field = this.fields[columnIndex]; + + switch (field.getMysqlType()) { + case MysqlDefs.FIELD_TYPE_BIT: + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + (valueAsLong < Byte.MIN_VALUE + || valueAsLong > Byte.MAX_VALUE)) { + throwRangeException(String.valueOf(valueAsLong), columnIndex + 1, + Types.TINYINT); + } + + return (byte)valueAsLong; + case MysqlDefs.FIELD_TYPE_TINY: + byte valueAsByte = ((byte[]) value)[0]; + + if (!field.isUnsigned()) { + return valueAsByte; + } + + short valueAsShort = (valueAsByte >= 0) ? + valueAsByte : (short)(valueAsByte + (short)256); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsShort > Byte.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsShort), + columnIndex + 1, Types.TINYINT); + } + } + + return (byte)valueAsShort; + + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + valueAsShort = getNativeShort(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsShort < Byte.MIN_VALUE + || valueAsShort > Byte.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsShort), + columnIndex + 1, Types.TINYINT); + } + } + + return (byte) valueAsShort; + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + int valueAsInt = getNativeInt(columnIndex + 1, false); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsInt < Byte.MIN_VALUE || valueAsInt > Byte.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsInt), + columnIndex + 1, Types.TINYINT); + } + } + + return (byte) valueAsInt; + + case MysqlDefs.FIELD_TYPE_FLOAT: + float valueAsFloat = getNativeFloat(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsFloat < Byte.MIN_VALUE + || valueAsFloat > Byte.MAX_VALUE) { + + throwRangeException(String.valueOf(valueAsFloat), + columnIndex + 1, Types.TINYINT); + } + } + + return (byte) valueAsFloat; + + case MysqlDefs.FIELD_TYPE_DOUBLE: + double valueAsDouble = getNativeDouble(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Byte.MIN_VALUE + || valueAsDouble > Byte.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.TINYINT); + } + } + + return (byte) valueAsDouble; + + case MysqlDefs.FIELD_TYPE_LONGLONG: + valueAsLong = getNativeLong(columnIndex + 1, false, true); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsLong < Byte.MIN_VALUE + || valueAsLong > Byte.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex + 1, Types.TINYINT); + } + } + + return (byte) valueAsLong; + + default: + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getByte()", columnIndex, + this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + return getByteFromString(getNativeString(columnIndex + 1), + columnIndex + 1); + } + } + + /** + * Get the value of a column in the current row as a Java byte array. + * + *

+ * Be warned If the blob is huge, then you may run out of memory. + *

+ * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database access error occurs + */ + protected byte[] getNativeBytes(int columnIndex, boolean noConversion) + throws SQLException { + checkRowPos(); + + checkColumnBounds(columnIndex); + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (value == null) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return null; + } + + Field field = this.fields[columnIndex - 1]; + + int mysqlType = field.getMysqlType(); + + // Workaround for emulated locators in servers > 4.1, + // as server returns SUBSTRING(blob) as STRING type... + if (noConversion) { + mysqlType = MysqlDefs.FIELD_TYPE_BLOB; + } + + switch (mysqlType) { + case MysqlDefs.FIELD_TYPE_TINY_BLOB: + case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: + case MysqlDefs.FIELD_TYPE_LONG_BLOB: + case MysqlDefs.FIELD_TYPE_BLOB: + case MysqlDefs.FIELD_TYPE_BIT: + return (byte[]) value; + + case MysqlDefs.FIELD_TYPE_STRING: + case MysqlDefs.FIELD_TYPE_VARCHAR: + case MysqlDefs.FIELD_TYPE_VAR_STRING: + if (value instanceof byte[]) { + return (byte[]) value; + } + // fallthrough + default: + int sqlType = field.getSQLType(); + + if (sqlType == Types.VARBINARY || sqlType == Types.BINARY) { + return (byte[]) value; + } + + return getBytesFromString(getNativeString(columnIndex)); + } + } + + /** + * JDBC 2.0 + * + *

+ * Get the value of a column in the current row as a java.io.Reader. + *

+ * + * @param columnIndex + * the column to get the value from + * + * @return the value in the column as a java.io.Reader. + * + * @throws SQLException + * if an error occurs + */ + protected java.io.Reader getNativeCharacterStream(int columnIndex) + throws SQLException { + int columnIndexMinusOne = columnIndex - 1; + + switch (this.fields[columnIndexMinusOne].getSQLType()) { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.CLOB: + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return this.thisRow.getReader(columnIndexMinusOne); + } + + String asString = getStringForClob(columnIndex); + + if (asString == null) { + return null; + } + + return getCharacterStreamFromString(asString); + } + + /** + * JDBC 2.0 Get a CLOB column. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @return an object representing a CLOB + * + * @throws SQLException + * if an error occurs + */ + protected java.sql.Clob getNativeClob(int columnIndex) throws SQLException { + String stringVal = getStringForClob(columnIndex); + + if (stringVal == null) { + return null; + } + + return getClobFromString(stringVal); + } + + private String getNativeConvertToString(int columnIndex, + Field field) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + int sqlType = field.getSQLType(); + int mysqlType = field.getMysqlType(); + + switch (sqlType) { + case Types.BIT: + return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex)); + case Types.BOOLEAN: + boolean booleanVal = getBoolean(columnIndex); + + if (this.wasNullFlag) { + return null; + } + + return String.valueOf(booleanVal); + + case Types.TINYINT: + byte tinyintVal = getNativeByte(columnIndex, false); + + if (this.wasNullFlag) { + return null; + } + + if (!field.isUnsigned() || tinyintVal >= 0) { + return String.valueOf(tinyintVal); + } + + short unsignedTinyVal = (short) (tinyintVal & 0xff); + + return String.valueOf(unsignedTinyVal); + + case Types.SMALLINT: + + int intVal = getNativeInt(columnIndex, false); + + if (this.wasNullFlag) { + return null; + } + + if (!field.isUnsigned() || intVal >= 0) { + return String.valueOf(intVal); + } + + intVal = intVal & 0xffff; + + return String.valueOf(intVal); + + case Types.INTEGER: + intVal = getNativeInt(columnIndex, false); + + if (this.wasNullFlag) { + return null; + } + + if (!field.isUnsigned() || intVal >= 0 + || field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) { + + return String.valueOf(intVal); + } + + long longVal = intVal & 0xffffffffL; + + return String.valueOf(longVal); + + case Types.BIGINT: + + if (!field.isUnsigned()) { + longVal = getNativeLong(columnIndex, false, true); + + if (this.wasNullFlag) { + return null; + } + + return String.valueOf(longVal); + } + + longVal = getNativeLong(columnIndex, false, false); + + if (this.wasNullFlag) { + return null; + } + + return String.valueOf(convertLongToUlong(longVal)); + case Types.REAL: + float floatVal = getNativeFloat(columnIndex); + + if (this.wasNullFlag) { + return null; + } + + return String.valueOf(floatVal); + + case Types.FLOAT: + case Types.DOUBLE: + double doubleVal = getNativeDouble(columnIndex); + + if (this.wasNullFlag) { + return null; + } + + return String.valueOf(doubleVal); + + case Types.DECIMAL: + case Types.NUMERIC: + String stringVal = StringUtils + .toAsciiString(this.thisRow.getColumnValue(columnIndex - 1)); + + BigDecimal val; + + if (stringVal != null) { + this.wasNullFlag = false; + + if (stringVal.length() == 0) { + val = new BigDecimal(0); + + return val.toString(); + } + + try { + val = new BigDecimal(stringVal); + } catch (NumberFormatException ex) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Bad_format_for_BigDecimal", + new Object[] {stringVal, Integer.valueOf(columnIndex)}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return val.toString(); + } + + this.wasNullFlag = true; + + return null; + + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + + return extractStringFromNativeColumn(columnIndex, mysqlType); + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + + if (!field.isBlob()) { + return extractStringFromNativeColumn(columnIndex, mysqlType); + } else if (!field.isBinary()) { + return extractStringFromNativeColumn(columnIndex, mysqlType); + } else { + byte[] data = getBytes(columnIndex); + Object obj = data; + + if ((data != null) && (data.length >= 2)) { + if ((data[0] == -84) && (data[1] == -19)) { + // Serialized object? + try { + ByteArrayInputStream bytesIn = new ByteArrayInputStream( + data); + ObjectInputStream objIn = new ObjectInputStream( + bytesIn); + obj = objIn.readObject(); + objIn.close(); + bytesIn.close(); + } catch (ClassNotFoundException cnfe) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$ + + cnfe.toString() + + Messages + .getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor()); //$NON-NLS-1$ + } catch (IOException ex) { + obj = data; // not serialized? + } + } + + return obj.toString(); + } + + return extractStringFromNativeColumn(columnIndex, mysqlType); + } + + case Types.DATE: + + // The YEAR datatype needs to be handled differently here. + if (mysqlType == MysqlDefs.FIELD_TYPE_YEAR) { + short shortVal = getNativeShort(columnIndex); + + if (!this.connection.getYearIsDateType()) { + + if (this.wasNullFlag) { + return null; + } + + return String.valueOf(shortVal); + } + + if (field.getLength() == 2) { + + if (shortVal <= 69) { + shortVal = (short) (shortVal + 100); + } + + shortVal += 1900; + } + + return fastDateCreate(null, shortVal, 1, 1).toString(); + + } + + if (this.connection.getNoDatetimeStringSync()) { + byte[] asBytes = getNativeBytes(columnIndex, true); + + if (asBytes == null) { + return null; + } + + if (asBytes.length == 0 /* newer versions of the server + seem to do this when they see all-zero datetime data */) { + return "0000-00-00"; + } + + int year = (asBytes[0] & 0xff) + | ((asBytes[1] & 0xff) << 8); + int month = asBytes[2]; + int day = asBytes[3]; + + if (year == 0 && month == 0 && day == 0) { + return "0000-00-00"; + } + } + + Date dt = getNativeDate(columnIndex); + + if (dt == null) { + return null; + } + + return String.valueOf(dt); + + case Types.TIME: + Time tm = getNativeTime(columnIndex, null, this.defaultTimeZone, false); + + if (tm == null) { + return null; + } + + return String.valueOf(tm); + + case Types.TIMESTAMP: + if (this.connection.getNoDatetimeStringSync()) { + byte[] asBytes = getNativeBytes(columnIndex, true); + + if (asBytes == null) { + return null; + } + + if (asBytes.length == 0 /* newer versions of the server + seem to do this when they see all-zero datetime data */) { + return "0000-00-00 00:00:00"; + } + + int year = (asBytes[0] & 0xff) + | ((asBytes[1] & 0xff) << 8); + int month = asBytes[2]; + int day = asBytes[3]; + + if (year == 0 && month == 0 && day == 0) { + return "0000-00-00 00:00:00"; + } + } + + Timestamp tstamp = getNativeTimestamp(columnIndex, + null, this.defaultTimeZone, false); + + if (tstamp == null) { + return null; + } + + String result = String.valueOf(tstamp); + + if (!this.connection.getNoDatetimeStringSync()) { + return result; + } + + if (result.endsWith(".0")) { + return result.substring(0, result.length() - 2); + } + + default: + return extractStringFromNativeColumn(columnIndex, mysqlType); + } + } + } + + /** + * Get the value of a column in the current row as a java.sql.Date object + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value; null if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected java.sql.Date getNativeDate(int columnIndex) throws SQLException { + return getNativeDate(columnIndex, null); + } + + /** + * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date + * object. Use the calendar to construct an appropriate millisecond value + * for the Date, if the underlying database doesn't store timezone + * information. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param tz + * the calendar to use in constructing the date + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + protected java.sql.Date getNativeDate(int columnIndex, Calendar cal) + throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + int mysqlType = this.fields[columnIndexMinusOne].getMysqlType(); + + java.sql.Date dateToReturn = null; + + if (mysqlType == MysqlDefs.FIELD_TYPE_DATE) { + + dateToReturn = this.thisRow.getNativeDate(columnIndexMinusOne, + this.connection, this, cal); + } else { + TimeZone tz = (cal != null) ? cal.getTimeZone() + : this.getDefaultTimeZone(); + + boolean rollForward = (tz != null && !tz.equals(this.getDefaultTimeZone())); + + dateToReturn = (Date) this.thisRow.getNativeDateTimeValue(columnIndexMinusOne, + null, Types.DATE, mysqlType, tz, rollForward, this.connection, + this); + } + + // + // normally, we allow ResultSetImpl methods to check for null first, + // but with DATETIME values we have this wacky need to support + // 0000-00-00 00:00:00 -> NULL, so we have to defer + // to the RowHolder implementation, and check the return value. + // + + if (dateToReturn == null) { + + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return dateToReturn; + } + + java.sql.Date getNativeDateViaParseConversion(int columnIndex) throws SQLException { + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getDate()", columnIndex, + this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1], + new int[] { MysqlDefs.FIELD_TYPE_DATE }); + } + + String stringVal = getNativeString(columnIndex); + + return getDateFromString(stringVal, columnIndex, null); + } + + /** + * Get the value of a column in the current row as a Java double. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected double getNativeDouble(int columnIndex) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + columnIndex--; // / JDBC is 1-based + + if (this.thisRow.isNull(columnIndex)) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + Field f= this.fields[columnIndex]; + + switch (f.getMysqlType()) { + case MysqlDefs.FIELD_TYPE_DOUBLE: + return this.thisRow.getNativeDouble(columnIndex); + case MysqlDefs.FIELD_TYPE_TINY: + if (!f.isUnsigned()) { + return getNativeByte(columnIndex + 1); + } + + return getNativeShort(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + if (!f.isUnsigned()) { + return getNativeShort(columnIndex + 1); + } + + return getNativeInt(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + if (!f.isUnsigned()) { + return getNativeInt(columnIndex + 1); + } + + return getNativeLong(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_LONGLONG: + long valueAsLong = getNativeLong(columnIndex + 1); + + if (!f.isUnsigned()) { + return valueAsLong; + } + + BigInteger asBigInt = convertLongToUlong(valueAsLong); + + // TODO: Check for overflow + + return asBigInt.doubleValue(); + case MysqlDefs.FIELD_TYPE_FLOAT: + return getNativeFloat(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_BIT: + return getNumericRepresentationOfSQLBitType(columnIndex + 1); + default: + String stringVal = getNativeString(columnIndex + 1); + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getDouble()", columnIndex, + stringVal, this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + return getDoubleFromString(stringVal, columnIndex + 1); + } + } + + /** + * Get the value of a column in the current row as a Java float. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected float getNativeFloat(int columnIndex) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + columnIndex--; // / JDBC is 1-based + + if (this.thisRow.isNull(columnIndex)) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + Field f = this.fields[columnIndex]; + + switch (f.getMysqlType()) { + case MysqlDefs.FIELD_TYPE_BIT: + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1); + + return valueAsLong; + case MysqlDefs.FIELD_TYPE_DOUBLE: + + // Only foolproof way to check for overflow + // Not efficient, but if you don't want to be inefficient, use the + // correct binding for the type! + + Double valueAsDouble = new Double(getNativeDouble(columnIndex + 1)); + + float valueAsFloat = valueAsDouble.floatValue(); + + if (this.jdbcCompliantTruncationForReads && + valueAsFloat == Float.NEGATIVE_INFINITY || + valueAsFloat == Float.POSITIVE_INFINITY) { + throwRangeException(valueAsDouble.toString(), + columnIndex + 1, Types.FLOAT); + } + + return (float) getNativeDouble(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_TINY: + if (!f.isUnsigned()) { + return getNativeByte(columnIndex + 1); + } + + return getNativeShort(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + if (!f.isUnsigned()) { + return getNativeShort(columnIndex + 1); + } + + return getNativeInt(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + if (!f.isUnsigned()) { + return getNativeInt(columnIndex + 1); + } + + return getNativeLong(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_LONGLONG: + valueAsLong = getNativeLong(columnIndex + 1); + + if (!f.isUnsigned()) { + return valueAsLong; + } + + BigInteger asBigInt = convertLongToUlong(valueAsLong); + + // TODO: Check for overflow + + return asBigInt.floatValue(); + case MysqlDefs.FIELD_TYPE_FLOAT: + + return this.thisRow.getNativeFloat(columnIndex); + + default: + String stringVal = getNativeString(columnIndex + 1); + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getFloat()", columnIndex, + stringVal, this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + return getFloatFromString(stringVal, columnIndex + 1); + } + } + + /** + * Get the value of a column in the current row as a Java int. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected int getNativeInt(int columnIndex) throws SQLException { + return getNativeInt(columnIndex, true); + } + + protected int getNativeInt(int columnIndex, boolean overflowCheck) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + columnIndex--; // / JDBC is 1-based + + if (this.thisRow.isNull(columnIndex)) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + Field f = this.fields[columnIndex]; + + switch (f.getMysqlType()) { + case MysqlDefs.FIELD_TYPE_BIT: + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + (valueAsLong < Integer.MIN_VALUE + || valueAsLong > Integer.MAX_VALUE)) { + throwRangeException(String.valueOf(valueAsLong), columnIndex + 1, + Types.INTEGER); + } + + return (short)valueAsLong; + case MysqlDefs.FIELD_TYPE_TINY: + byte tinyintVal = getNativeByte(columnIndex + 1, false); + + if (!f.isUnsigned() || tinyintVal >= 0) { + return tinyintVal; + } + + return tinyintVal + 256; + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + short asShort = getNativeShort(columnIndex + 1, false); + + if (!f.isUnsigned() || asShort >= 0) { + return asShort; + } + + return asShort + 65536; + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + + int valueAsInt = this.thisRow.getNativeInt(columnIndex); + + if (!f.isUnsigned()) { + return valueAsInt; + } + + valueAsLong = (valueAsInt >= 0) ? + valueAsInt : valueAsInt + 4294967296L; + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + valueAsLong > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex + 1, Types.INTEGER); + } + + return (int)valueAsLong; + case MysqlDefs.FIELD_TYPE_LONGLONG: + valueAsLong = getNativeLong(columnIndex + 1, false, true); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsLong < Integer.MIN_VALUE + || valueAsLong > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex + 1, Types.INTEGER); + } + } + + return (int) valueAsLong; + case MysqlDefs.FIELD_TYPE_DOUBLE: + double valueAsDouble = getNativeDouble(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Integer.MIN_VALUE + || valueAsDouble > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.INTEGER); + } + } + + return (int) valueAsDouble; + case MysqlDefs.FIELD_TYPE_FLOAT: + valueAsDouble = getNativeFloat(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Integer.MIN_VALUE + || valueAsDouble > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.INTEGER); + } + } + + return (int) valueAsDouble; + + default: + String stringVal = getNativeString(columnIndex + 1); + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getInt()", columnIndex, + stringVal, this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + return getIntFromString(stringVal, columnIndex + 1); + } + } + + /** + * Get the value of a column in the current row as a Java long. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected long getNativeLong(int columnIndex) throws SQLException { + return getNativeLong(columnIndex, true, true); + } + + protected long getNativeLong(int columnIndex, boolean overflowCheck, + boolean expandUnsignedLong) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + columnIndex--; // / JDBC is 1-based + + if (this.thisRow.isNull(columnIndex)) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + Field f = this.fields[columnIndex]; + + switch (f.getMysqlType()) { + case MysqlDefs.FIELD_TYPE_BIT: + return getNumericRepresentationOfSQLBitType(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_TINY: + if (!f.isUnsigned()) { + return getNativeByte(columnIndex + 1); + } + + return getNativeInt(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_SHORT: + if (!f.isUnsigned()) { + return getNativeShort(columnIndex + 1); + } + + return getNativeInt(columnIndex + 1, false); + case MysqlDefs.FIELD_TYPE_YEAR: + + return getNativeShort(columnIndex + 1); + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + int asInt = getNativeInt(columnIndex + 1, false); + + if (!f.isUnsigned() || asInt >= 0) { + return asInt; + } + + return asInt + 4294967296L; + case MysqlDefs.FIELD_TYPE_LONGLONG: + long valueAsLong = this.thisRow.getNativeLong(columnIndex); + + if (!f.isUnsigned() || !expandUnsignedLong) { + return valueAsLong; + } + + BigInteger asBigInt = convertLongToUlong(valueAsLong); + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + ((asBigInt.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0 ) || + (asBigInt.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0))) { + throwRangeException(asBigInt.toString(), + columnIndex + 1, Types.BIGINT); + } + + return getLongFromString(asBigInt.toString(), columnIndex); + + case MysqlDefs.FIELD_TYPE_DOUBLE: + double valueAsDouble = getNativeDouble(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Long.MIN_VALUE + || valueAsDouble > Long.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.BIGINT); + } + } + + return (long) valueAsDouble; + case MysqlDefs.FIELD_TYPE_FLOAT: + valueAsDouble = getNativeFloat(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Long.MIN_VALUE + || valueAsDouble > Long.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.BIGINT); + } + } + + return (long) valueAsDouble; + default: + String stringVal = getNativeString(columnIndex + 1); + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getLong()", columnIndex, + stringVal, this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + return getLongFromString(stringVal, columnIndex + 1); + } + } + + /** + * JDBC 2.0 Get a REF(<structured-type>) column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing data of an SQL REF type + * + * @throws SQLException + * as this is not implemented + * @throws NotImplemented + * DOCUMENT ME! + */ + protected java.sql.Ref getNativeRef(int i) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * Get the value of a column in the current row as a Java short. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected short getNativeShort(int columnIndex) throws SQLException { + return getNativeShort(columnIndex, true); + } + + protected short getNativeShort(int columnIndex, boolean overflowCheck) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + columnIndex--; // / JDBC is 1-based + + + if (this.thisRow.isNull(columnIndex)) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + Field f = this.fields[columnIndex]; + + switch (f.getMysqlType()) { + + case MysqlDefs.FIELD_TYPE_TINY: + byte tinyintVal = getNativeByte(columnIndex + 1, false); + + if (!f.isUnsigned() || tinyintVal >= 0) { + return tinyintVal; + } + + return (short)(tinyintVal + (short)256); + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + + short asShort = this.thisRow.getNativeShort(columnIndex); + + if (!f.isUnsigned()) { + return asShort; + } + + int valueAsInt = asShort & 0xffff; + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + valueAsInt > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsInt), + columnIndex + 1, Types.SMALLINT); + } + + return (short)valueAsInt; + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + if (!f.isUnsigned()) { + valueAsInt = getNativeInt(columnIndex + 1, false); + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + valueAsInt > Short.MAX_VALUE || + valueAsInt < Short.MIN_VALUE) { + throwRangeException(String.valueOf(valueAsInt), + columnIndex + 1, Types.SMALLINT); + } + + return (short)valueAsInt; + } + + long valueAsLong = getNativeLong(columnIndex + 1, false, true); + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + valueAsLong > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex + 1, Types.SMALLINT); + } + + return (short)valueAsLong; + + case MysqlDefs.FIELD_TYPE_LONGLONG: + valueAsLong = getNativeLong(columnIndex + 1, false, false); + + if (!f.isUnsigned()) { + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsLong < Short.MIN_VALUE + || valueAsLong > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex + 1, Types.SMALLINT); + } + } + + return (short) valueAsLong; + } + + BigInteger asBigInt = convertLongToUlong(valueAsLong); + + if (overflowCheck && this.jdbcCompliantTruncationForReads && + ((asBigInt.compareTo(new BigInteger(String.valueOf(Short.MAX_VALUE))) > 0 ) || + (asBigInt.compareTo(new BigInteger(String.valueOf(Short.MIN_VALUE))) < 0))) { + throwRangeException(asBigInt.toString(), + columnIndex + 1, Types.SMALLINT); + } + + return (short)getIntFromString(asBigInt.toString(), columnIndex + 1); + + case MysqlDefs.FIELD_TYPE_DOUBLE: + double valueAsDouble = getNativeDouble(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Short.MIN_VALUE + || valueAsDouble > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.SMALLINT); + } + } + + return (short) valueAsDouble; + case MysqlDefs.FIELD_TYPE_FLOAT: + float valueAsFloat = getNativeFloat(columnIndex + 1); + + if (overflowCheck && this.jdbcCompliantTruncationForReads) { + if (valueAsFloat < Short.MIN_VALUE + || valueAsFloat > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsFloat), + columnIndex + 1, Types.SMALLINT); + } + } + + return (short) valueAsFloat; + default: + String stringVal = getNativeString(columnIndex + 1); + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getShort()", columnIndex, + stringVal, this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + return getShortFromString(stringVal, columnIndex + 1); + } + } + + /** + * Get the value of a column in the current row as a Java String + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value, null for SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected String getNativeString(int columnIndex) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + if (this.fields == null) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Query_generated_no_fields_for_ResultSet_133"), //$NON-NLS-1$ + SQLError.SQL_STATE_INVALID_COLUMN_NUMBER, getExceptionInterceptor()); + } + + if (this.thisRow.isNull(columnIndex - 1)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + String stringVal = null; + + Field field = this.fields[columnIndex - 1]; + + // TODO: Check Types Here. + stringVal = getNativeConvertToString(columnIndex, field); + int mysqlType = field.getMysqlType(); + + if (mysqlType != MysqlDefs.FIELD_TYPE_TIMESTAMP && + mysqlType != MysqlDefs.FIELD_TYPE_DATE && + field.isZeroFill() && (stringVal != null)) { + int origLength = stringVal.length(); + + StringBuffer zeroFillBuf = new StringBuffer(origLength); + + long numZeros = field.getLength() - origLength; + + for (long i = 0; i < numZeros; i++) { + zeroFillBuf.append('0'); + } + + zeroFillBuf.append(stringVal); + + stringVal = zeroFillBuf.toString(); + } + + return stringVal; + } + + private Time getNativeTime(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward) + throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + int mysqlType = this.fields[columnIndexMinusOne].getMysqlType(); + + Time timeVal = null; + + if (mysqlType == MysqlDefs.FIELD_TYPE_TIME) { + timeVal = this.thisRow.getNativeTime(columnIndexMinusOne, + targetCalendar, tz, rollForward, this.connection, this); + + } else { + timeVal = (Time) this.thisRow.getNativeDateTimeValue(columnIndexMinusOne, + null, Types.TIME, mysqlType, tz, rollForward, this.connection, + this); + } + + // + // normally, we allow ResultSetImpl methods to check for null first, + // but with DATETIME values we have this wacky need to support + // 0000-00-00 00:00:00 -> NULL, so we have to defer + // to the RowHolder implementation, and check the return value. + // + + if (timeVal == null) { + + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return timeVal; + } + + Time getNativeTimeViaParseConversion(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward) throws SQLException { + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getTime()", columnIndex, + this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1], + new int[] { MysqlDefs.FIELD_TYPE_TIME }); + } + + String strTime = getNativeString(columnIndex); + + return getTimeFromString(strTime, targetCalendar, columnIndex, tz, rollForward); + } + + private Timestamp getNativeTimestamp(int columnIndex, + Calendar targetCalendar, + TimeZone tz, + boolean rollForward) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + Timestamp tsVal = null; + + int mysqlType = this.fields[columnIndexMinusOne].getMysqlType(); + + switch (mysqlType) { + case MysqlDefs.FIELD_TYPE_DATETIME: + case MysqlDefs.FIELD_TYPE_TIMESTAMP: + tsVal = this.thisRow.getNativeTimestamp(columnIndexMinusOne, + targetCalendar, tz, rollForward, this.connection, this); + break; + + default: + + + tsVal = (Timestamp) this.thisRow.getNativeDateTimeValue( + columnIndexMinusOne, null, Types.TIMESTAMP, mysqlType, tz, + rollForward, this.connection, this); + } + + // + // normally, we allow ResultSetImpl methods to check for null first, + // but with DATETIME values we have this wacky need to support + // 0000-00-00 00:00:00 -> NULL, so we have to defer + // to the RowHolder implementation, and check the return value. + // + + if (tsVal == null) { + + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return tsVal; + } + + Timestamp getNativeTimestampViaParseConversion(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward) throws SQLException { + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getTimestamp()", columnIndex, + this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1], + new int[] { MysqlDefs.FIELD_TYPE_TIMESTAMP, + MysqlDefs.FIELD_TYPE_DATETIME }); + } + + String strTimestamp = getNativeString(columnIndex); + + return getTimestampFromString(columnIndex, targetCalendar, strTimestamp, tz, + rollForward); + } + + // --------------------------------------------------------------------- + // Updates + // --------------------------------------------------------------------- + + /** + * A column value can also be retrieved as a stream of Unicode characters. + * We implement this as a binary stream. + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return a Java InputStream that delivers the database column value as a + * stream of two byte Unicode characters. If the value is SQL NULL, + * then the result is null + * + * @exception SQLException + * if a database access error occurs + * + * @see getAsciiStream + * @see getBinaryStream + */ + protected InputStream getNativeUnicodeStream(int columnIndex) + throws SQLException { + checkRowPos(); + + return getBinaryStream(columnIndex); + } + + /** + * @see ResultSetInternalMethods#getURL(int) + */ + protected URL getNativeURL(int colIndex) throws SQLException { + String val = getString(colIndex); + + if (val == null) { + return null; + } + + try { + return new URL(val); + } catch (MalformedURLException mfe) { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Malformed_URL____141") + + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * DOCUMENT ME! + * + * @return Returns the nextResultSet, if any, null if none exists. + */ + public synchronized ResultSetInternalMethods getNextResultSet() { + return this.nextResultSet; + } + + /** + * Get the value of a column in the current row as a Java object + * + *

+ * This method will return the value of the given column as a Java object. + * The type of the Java object will be the default Java Object type + * corresponding to the column's SQL type, following the mapping specified + * in the JDBC specification. + *

+ * + *

+ * This method may also be used to read database specific abstract data + * types. + *

+ * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return a Object holding the column value + * + * @exception SQLException + * if a database access error occurs + */ + public Object getObject(int columnIndex) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + Field field; + field = this.fields[columnIndexMinusOne]; + + switch (field.getSQLType()) { + case Types.BIT: + case Types.BOOLEAN: + if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT + && !field.isSingleBit()) { + return getBytes(columnIndex); + } + + // valueOf would be nicer here, but it isn't + // present in JDK-1.3.1, which is what the CTS + // uses. + return Boolean.valueOf(getBoolean(columnIndex)); + + case Types.TINYINT: + if (!field.isUnsigned()) { + return Integer.valueOf(getByte(columnIndex)); + } + + return Integer.valueOf(getInt(columnIndex)); + + case Types.SMALLINT: + + return Integer.valueOf(getInt(columnIndex)); + + case Types.INTEGER: + + if (!field.isUnsigned() || + field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) { + return Integer.valueOf(getInt(columnIndex)); + } + + return Long.valueOf(getLong(columnIndex)); + + case Types.BIGINT: + + if (!field.isUnsigned()) { + return Long.valueOf(getLong(columnIndex)); + } + + String stringVal = getString(columnIndex); + + if (stringVal == null) { + return null; + } + + try { + return new BigInteger(stringVal); + } catch (NumberFormatException nfe) { + throw SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_BigInteger", new Object[] { + Integer.valueOf(columnIndex), stringVal }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + case Types.DECIMAL: + case Types.NUMERIC: + stringVal = getString(columnIndex); + + BigDecimal val; + + if (stringVal != null) { + if (stringVal.length() == 0) { + val = new BigDecimal(0); + + return val; + } + + try { + val = new BigDecimal(stringVal); + } catch (NumberFormatException ex) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Bad_format_for_BigDecimal", //$NON-NLS-1$ + new Object[] {stringVal, Integer.valueOf(columnIndex)}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return val; + } + + return null; + + case Types.REAL: + return new Float(getFloat(columnIndex)); + + case Types.FLOAT: + case Types.DOUBLE: + return new Double(getDouble(columnIndex)); + + case Types.CHAR: + case Types.VARCHAR: + if (!field.isOpaqueBinary()) { + return getString(columnIndex); + } + + return getBytes(columnIndex); + case Types.LONGVARCHAR: + if (!field.isOpaqueBinary()) { + return getStringForClob(columnIndex); + } + + return getBytes(columnIndex); + + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_GEOMETRY) { + return getBytes(columnIndex); + } else if (field.isBinary() || field.isBlob()) { + byte[] data = getBytes(columnIndex); + + if (this.connection.getAutoDeserialize()) { + Object obj = data; + + if ((data != null) && (data.length >= 2)) { + if ((data[0] == -84) && (data[1] == -19)) { + // Serialized object? + try { + ByteArrayInputStream bytesIn = new ByteArrayInputStream( + data); + ObjectInputStream objIn = new ObjectInputStream( + bytesIn); + obj = objIn.readObject(); + objIn.close(); + bytesIn.close(); + } catch (ClassNotFoundException cnfe) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$ + + cnfe.toString() + + Messages + .getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor()); //$NON-NLS-1$ + } catch (IOException ex) { + obj = data; // not serialized? + } + } else { + return getString(columnIndex); + } + } + + return obj; + } + + return data; + } + + return getBytes(columnIndex); + + case Types.DATE: + if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR + && !this.connection.getYearIsDateType()) { + return Short.valueOf(getShort(columnIndex)); + } + + return getDate(columnIndex); + + case Types.TIME: + return getTime(columnIndex); + + case Types.TIMESTAMP: + return getTimestamp(columnIndex); + + default: + return getString(columnIndex); + } + } + + @SuppressWarnings("unchecked") + public T getObject(int columnIndex, Class type) throws SQLException { + if (type == null) { + throw SQLError.createSQLException("Type parameter can not be null", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (type.equals(String.class)) { + return (T) getString(columnIndex); + } else if (type.equals(BigDecimal.class)) { + return (T) getBigDecimal(columnIndex); + } else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) { + return (T) Boolean.valueOf(getBoolean(columnIndex)); + } else if (type.equals(Integer.class) || type.equals(Integer.TYPE)) { + return (T) Integer.valueOf(getInt(columnIndex)); + } else if (type.equals(Long.class) || type.equals(Long.TYPE)) { + return (T) Long.valueOf(getLong(columnIndex)); + } else if (type.equals(Float.class) || type.equals(Float.TYPE)) { + return (T) Float.valueOf(getFloat(columnIndex)); + } else if (type.equals(Double.class) || type.equals(Double.TYPE)) { + return (T) Double.valueOf(getDouble(columnIndex)); + } else if (type.equals(byte[].class)) { + return (T) getBytes(columnIndex); + } else if (type.equals(java.sql.Date.class)) { + return (T) getDate(columnIndex); + } else if (type.equals(Time.class)) { + return (T) getTime(columnIndex); + } else if (type.equals(Timestamp.class)) { + return (T) getTimestamp(columnIndex); + } else if (type.equals(Clob.class)) { + return (T) getClob(columnIndex); + } else if (type.equals(Blob.class)) { + return (T) getBlob(columnIndex); + } else if (type.equals(Array.class)) { + return (T) getArray(columnIndex); + } else if (type.equals(Ref.class)) { + return (T) getRef(columnIndex); + } else if (type.equals(URL.class)) { + return (T) getURL(columnIndex); +// } else if (type.equals(Struct.class)) { +// +// } +// } else if (type.equals(RowId.class)) { +// +// } else if (type.equals(NClob.class)) { +// +// } else if (type.equals(SQLXML.class)) { + + } else { + if (this.connection.getAutoDeserialize()) { + try { + return (T) getObject(columnIndex); + } catch (ClassCastException cce) { + SQLException sqlEx = SQLError.createSQLException("Conversion not supported for type " + type.getName(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + sqlEx.initCause(cce); + + throw sqlEx; + } + } + + throw SQLError.createSQLException("Conversion not supported for type " + type.getName(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + // JDBC-4.1 + public T getObject(String columnLabel, Class type) throws SQLException { + return getObject(findColumn(columnLabel), type); + } + + /** + * JDBC 2.0 Returns the value of column i as a Java object. Use the map to + * determine the class from which to construct data of SQL structured and + * distinct types. + * + * @param i + * the first column is 1, the second is 2, ... + * @param map + * the mapping from SQL type names to Java classes + * + * @return an object representing the SQL value + * + * @throws SQLException + * because this is not implemented + */ + public Object getObject(int i, java.util.Map> map) throws SQLException { + return getObject(i); + } + + /** + * Get the value of a column in the current row as a Java object + * + *

+ * This method will return the value of the given column as a Java object. + * The type of the Java object will be the default Java Object type + * corresponding to the column's SQL type, following the mapping specified + * in the JDBC specification. + *

+ * + *

+ * This method may also be used to read database specific abstract data + * types. + *

+ * + * @param columnName + * is the SQL name of the column + * + * @return a Object holding the column value + * + * @exception SQLException + * if a database access error occurs + */ + public Object getObject(String columnName) throws SQLException { + return getObject(findColumn(columnName)); + } + + /** + * JDBC 2.0 Returns the value of column i as a Java object. Use the map to + * determine the class from which to construct data of SQL structured and + * distinct types. + * + * @param colName + * the column name + * @param map + * the mapping from SQL type names to Java classes + * + * @return an object representing the SQL value + * + * @throws SQLException + * as this is not implemented + */ + public Object getObject(String colName, java.util.Map> map) + throws SQLException { + return getObject(findColumn(colName), map); + } + + public Object getObjectStoredProc(int columnIndex, int desiredSqlType) + throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (value == null) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + Field field; + field = this.fields[columnIndex - 1]; + + switch (desiredSqlType) { + case Types.BIT: + case Types.BOOLEAN: + // valueOf would be nicer here, but it isn't + // present in JDK-1.3.1, which is what the CTS + // uses. + return Boolean.valueOf(getBoolean(columnIndex)); + + case Types.TINYINT: + return Integer.valueOf(getInt(columnIndex)); + + case Types.SMALLINT: + return Integer.valueOf(getInt(columnIndex)); + + case Types.INTEGER: + + if (!field.isUnsigned() || + field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) { + return Integer.valueOf(getInt(columnIndex)); + } + + return Long.valueOf(getLong(columnIndex)); + + case Types.BIGINT: + + if (field.isUnsigned()) { + return getBigDecimal(columnIndex); + } + + return Long.valueOf(getLong(columnIndex)); + + case Types.DECIMAL: + case Types.NUMERIC: + + String stringVal = getString(columnIndex); + BigDecimal val; + + if (stringVal != null) { + if (stringVal.length() == 0) { + val = new BigDecimal(0); + + return val; + } + + try { + val = new BigDecimal(stringVal); + } catch (NumberFormatException ex) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Bad_format_for_BigDecimal", //$NON-NLS-1$ + new Object[] {stringVal, Integer.valueOf(columnIndex)}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + return val; + } + + return null; + + case Types.REAL: + return new Float(getFloat(columnIndex)); + + case Types.FLOAT: + + if (!this.connection.getRunningCTS13()) { + return new Double(getFloat(columnIndex)); + } + return new Float(getFloat(columnIndex)); // NB - bug in JDBC + // compliance test, + // according + // to JDBC spec, FLOAT type should return DOUBLE + // but causes ClassCastException in CTS :( + + case Types.DOUBLE: + return new Double(getDouble(columnIndex)); + + case Types.CHAR: + case Types.VARCHAR: + return getString(columnIndex); + case Types.LONGVARCHAR: + return getStringForClob(columnIndex); + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + return getBytes(columnIndex); + + case Types.DATE: + if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR + && !this.connection.getYearIsDateType()) { + return Short.valueOf(getShort(columnIndex)); + } + + return getDate(columnIndex); + + case Types.TIME: + return getTime(columnIndex); + + case Types.TIMESTAMP: + return getTimestamp(columnIndex); + + default: + return getString(columnIndex); + } + } + + public Object getObjectStoredProc(int i, java.util.Map map, + int desiredSqlType) throws SQLException { + return getObjectStoredProc(i, desiredSqlType); + } + + public Object getObjectStoredProc(String columnName, int desiredSqlType) + throws SQLException { + return getObjectStoredProc(findColumn(columnName), desiredSqlType); + } + + public Object getObjectStoredProc(String colName, java.util.Map map, + int desiredSqlType) throws SQLException { + return getObjectStoredProc(findColumn(colName), map, desiredSqlType); + } + + /** + * JDBC 2.0 Get a REF(<structured-type>) column. + * + * @param i + * the first column is 1, the second is 2, ... + * + * @return an object representing data of an SQL REF type + * + * @throws SQLException + * as this is not implemented + * @throws NotImplemented + * DOCUMENT ME! + */ + public java.sql.Ref getRef(int i) throws SQLException { + checkColumnBounds(i); + throw SQLError.notImplemented(); + } + + /** + * JDBC 2.0 Get a REF(<structured-type>) column. + * + * @param colName + * the column name + * + * @return an object representing data of an SQL REF type + * + * @throws SQLException + * as this method is not implemented. + * @throws NotImplemented + * DOCUMENT ME! + */ + public java.sql.Ref getRef(String colName) throws SQLException { + return getRef(findColumn(colName)); + } + + /** + * JDBC 2.0 + * + *

+ * Determine the current row number. The first row is number 1, the second + * number 2, etc. + *

+ * + * @return the current row number, else return 0 if there is no current row + * + * @exception SQLException + * if a database-access error occurs. + */ + public int getRow() throws SQLException { + checkClosed(); + + int currentRowNumber = this.rowData.getCurrentRowNumber(); + int row = 0; + + // Non-dynamic result sets can be interrogated + // for this information + if (!this.rowData.isDynamic()) { + if ((currentRowNumber < 0) || this.rowData.isAfterLast() + || this.rowData.isEmpty()) { + row = 0; + } else { + row = currentRowNumber + 1; + } + } else { + // dynamic (streaming) can not + row = currentRowNumber + 1; + } + + return row; + } + + /** + * Returns the server info (if any), or null if none. + * + * @return server info created for this ResultSet + */ + public String getServerInfo() { + try { + synchronized (checkClosed().getConnectionMutex()) { + return this.serverInfo; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + private long getNumericRepresentationOfSQLBitType(int columnIndex) throws SQLException { + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (this.fields[columnIndex - 1].isSingleBit() || + ((byte[])value).length == 1) { + return ((byte[])value)[0]; + } + + + byte[] asBytes = (byte[])value; + + + int shift = 0; + + long[] steps = new long[asBytes.length]; + + for (int i = asBytes.length - 1; i >= 0; i--) { + steps[i] = (long)(asBytes[i] & 0xff) << shift; + shift += 8; + } + + long valueAsLong = 0; + + for (int i = 0; i < asBytes.length; i++) { + valueAsLong |= steps[i]; + } + + return valueAsLong; + } + + /** + * Get the value of a column in the current row as a Java short. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public short getShort(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + checkRowPos(); + + if (this.useFastIntParsing) { + + checkColumnBounds(columnIndex); + + Object value = this.thisRow.getColumnValue(columnIndex - 1); + + if (value == null) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + if (this.wasNullFlag) { + return 0; + } + + byte[] shortAsBytes = (byte[]) value; + + if (shortAsBytes.length == 0) { + return (short) convertToZeroWithEmptyCheck(); + } + + boolean needsFullParse = false; + + for (int i = 0; i < shortAsBytes.length; i++) { + if (((char) shortAsBytes[i] == 'e') + || ((char) shortAsBytes[i] == 'E')) { + needsFullParse = true; + + break; + } + } + + if (!needsFullParse) { + try { + return parseShortWithOverflowCheck(columnIndex, + shortAsBytes, null); + } catch (NumberFormatException nfe) { + try { + // To do: Warn of over/underflow??? + return parseShortAsDouble(columnIndex, StringUtils.toString( + shortAsBytes)); + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex); + + if (this.jdbcCompliantTruncationForReads && + (valueAsLong < Short.MIN_VALUE + || valueAsLong > Short.MAX_VALUE)) { + throwRangeException(String.valueOf(valueAsLong), columnIndex, + Types.SMALLINT); + } + + return (short)valueAsLong; + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getShort()_-____96") + + StringUtils.toString(shortAsBytes) //$NON-NLS-1$ + + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + } + + String val = null; + + try { + val = getString(columnIndex); + + if ((val != null)) { + + if (val.length() == 0) { + return (short) convertToZeroWithEmptyCheck(); + } + + if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) + && (val.indexOf(".") == -1)) { + return parseShortWithOverflowCheck(columnIndex, null, + val); + } + + // Convert floating point + return parseShortAsDouble(columnIndex, val); + } + + return 0; // for NULL + } catch (NumberFormatException nfe) { + try { + return parseShortAsDouble(columnIndex, val); + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex); + + if (this.jdbcCompliantTruncationForReads && + (valueAsLong < Short.MIN_VALUE + || valueAsLong > Short.MAX_VALUE)) { + throwRangeException(String.valueOf(valueAsLong), columnIndex, + Types.SMALLINT); + } + + return (short)valueAsLong; + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getShort()_-____96") + + val //$NON-NLS-1$ + + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return getNativeShort(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public short getShort(String columnName) throws SQLException { + return getShort(findColumn(columnName)); + } + + private final short getShortFromString(String val, int columnIndex) + throws SQLException { + try { + if ((val != null)) { + + if (val.length() == 0) { + return (short) convertToZeroWithEmptyCheck(); + } + + if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) + && (val.indexOf(".") == -1)) { + return parseShortWithOverflowCheck(columnIndex, null, val); + } + + // Convert floating point + return parseShortAsDouble(columnIndex, val); + } + + return 0; // for NULL + } catch (NumberFormatException nfe) { + try { + return parseShortAsDouble(columnIndex, val); + } catch (NumberFormatException newNfe) { + ; // ignore, it's not a number + } + + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Invalid_value_for_getShort()_-____217") + + val //$NON-NLS-1$ + + Messages.getString("ResultSet.___in_column__218") + + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * JDBC 2.0 Return the Statement that produced the ResultSet. + * + * @return the Statment that produced the result set, or null if the result + * was produced some other way. + * + * @exception SQLException + * if a database-access error occurs + */ + public java.sql.Statement getStatement() throws SQLException { + try { + synchronized (checkClosed().getConnectionMutex()) { + if (this.wrapperStatement != null) { + return this.wrapperStatement; + } + + return this.owningStatement; + } + + } catch (SQLException sqlEx) { + if (!this.retainOwningStatement) { + throw SQLError.createSQLException( + "Operation not allowed on closed ResultSet. Statements " + + "can be retained over result set closure by setting the connection property " + + "\"retainStatementAfterResultSetClose\" to \"true\".", + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + } + + if (this.wrapperStatement != null) { + return this.wrapperStatement; + } + + return this.owningStatement; + } + + } + + /** + * Get the value of a column in the current row as a Java String + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value, null for SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + public String getString(int columnIndex) throws SQLException { + String stringVal = getStringInternal(columnIndex, true); + + if (this.padCharsWithSpace && stringVal != null) { + Field f = this.fields[columnIndex - 1]; + + if (f.getMysqlType() == MysqlDefs.FIELD_TYPE_STRING ) { + int fieldLength = (int)f.getLength() /* safe, bytes in a CHAR <= 1024 */ / + f.getMaxBytesPerCharacter(); /* safe, this will never be 0 */ + + int currentLength = stringVal.length(); + + if (currentLength < fieldLength) { + StringBuffer paddedBuf = new StringBuffer(fieldLength); + paddedBuf.append(stringVal); + + int difference = fieldLength - currentLength; + + paddedBuf.append(EMPTY_SPACE, 0, difference); + + stringVal = paddedBuf.toString(); + } + } + } + + return stringVal; + } + + /** + * The following routines simply convert the columnName into a columnIndex + * and then call the appropriate routine above. + * + * @param columnName + * is the SQL name of the column + * + * @return the column value + * + * @exception SQLException + * if a database access error occurs + */ + public String getString(String columnName) throws SQLException { + return getString(findColumn(columnName)); + } + + private String getStringForClob(int columnIndex) throws SQLException { + String asString = null; + + String forcedEncoding = + this.connection.getClobCharacterEncoding(); + + if (forcedEncoding == null) { + if (!this.isBinaryEncoded) { + asString = getString(columnIndex); + } else { + asString = getNativeString(columnIndex); + } + } else { + try { + byte[] asBytes = null; + + if (!this.isBinaryEncoded) { + asBytes = getBytes(columnIndex); + } else { + asBytes = getNativeBytes(columnIndex, true); + } + + if (asBytes != null) { + asString = StringUtils.toString(asBytes, forcedEncoding); + } + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException("Unsupported character encoding " + + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + return asString; + } + + protected String getStringInternal(int columnIndex, boolean checkDateTypes) + throws SQLException { + if (!this.isBinaryEncoded) { + checkRowPos(); + checkColumnBounds(columnIndex); + + if (this.fields == null) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Query_generated_no_fields_for_ResultSet_99"), //$NON-NLS-1$ + SQLError.SQL_STATE_INVALID_COLUMN_NUMBER, getExceptionInterceptor()); + } + + // JDBC is 1-based, Java is not !? + + int internalColumnIndex = columnIndex - 1; + + if (this.thisRow.isNull(internalColumnIndex)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + + Field metadata = this.fields[internalColumnIndex]; + + String stringVal = null; + + if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) { + if (metadata.isSingleBit()) { + byte[] value = this.thisRow.getColumnValue(internalColumnIndex); + + if (value.length == 0) { + return String.valueOf(convertToZeroWithEmptyCheck()); + } + + return String.valueOf(value[0]); + } + + return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex)); + } + + String encoding = metadata.getCharacterSet(); + + stringVal = this.thisRow.getString(internalColumnIndex, encoding, this.connection); + + // + // Special handling for YEAR type from mysql, some people + // want it as a DATE, others want to treat it as a SHORT + // + + if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { + if (!this.connection.getYearIsDateType()) { + return stringVal; + } + + Date dt = getDateFromString(stringVal, columnIndex, null); + + if (dt == null) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return dt.toString(); + } + + // Handles timezone conversion and zero-date behavior + + if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) { + switch (metadata.getSQLType()) { + case Types.TIME: + Time tm = getTimeFromString(stringVal, null, columnIndex, + this.getDefaultTimeZone(), false); + + if (tm == null) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return tm.toString(); + case Types.DATE: + + Date dt = getDateFromString(stringVal, columnIndex, null); + + if (dt == null) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return dt.toString(); + case Types.TIMESTAMP: + Timestamp ts = getTimestampFromString(columnIndex, + null, stringVal, this.getDefaultTimeZone(), false); + + if (ts == null) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return ts.toString(); + default: + break; + } + } + + return stringVal; + } + + return getNativeString(columnIndex); + } + + /** + * Get the value of a column in the current row as a java.sql.Time object + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value; null if SQL NULL + * + * @throws java.sql.SQLException + * if a database access error occurs + */ + public Time getTime(int columnIndex) throws java.sql.SQLException { + return getTimeInternal(columnIndex, null, this.getDefaultTimeZone(), false); + } + + /** + * Get the value of a column in the current row as a java.sql.Time object. + * Use the calendar to construct an appropriate millisecond value for the + * Time, if the underlying database doesn't store timezone information. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param cal + * the calendar to use in constructing the time + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Time getTime(int columnIndex, Calendar cal) + throws SQLException { + return getTimeInternal(columnIndex, cal, cal.getTimeZone(), true); + } + + /** + * Get the value of a column in the current row as a java.sql.Time object. + * + * @param columnName + * is the SQL name of the column + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @throws java.sql.SQLException + * if a database-access error occurs. + */ + public Time getTime(String columnName) throws java.sql.SQLException { + return getTime(findColumn(columnName)); + } + + /** + * Get the value of a column in the current row as a java.sql.Time object. + * Use the calendar to construct an appropriate millisecond value for the + * Time, if the underlying database doesn't store timezone information. + * + * @param columnName + * is the SQL name of the column + * @param cal + * the calendar to use in constructing the time + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Time getTime(String columnName, Calendar cal) + throws SQLException { + return getTime(findColumn(columnName), cal); + } + + private Time getTimeFromString(String timeAsString, Calendar targetCalendar, + int columnIndex, + TimeZone tz, + boolean rollForward) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + int hr = 0; + int min = 0; + int sec = 0; + + try { + + if (timeAsString == null) { + this.wasNullFlag = true; + + return null; + } + + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + timeAsString = timeAsString.trim(); + + if (timeAsString.equals("0") + || timeAsString.equals("0000-00-00") + || timeAsString.equals("0000-00-00 00:00:00") + || timeAsString.equals("00000000000000")) { + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(this.connection.getZeroDateTimeBehavior())) { + this.wasNullFlag = true; + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(this.connection.getZeroDateTimeBehavior())) { + throw SQLError.createSQLException("Value '" + timeAsString + + "' can not be represented as java.sql.Time", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + // We're left with the case of 'round' to a time Java _can_ + // represent, which is '00:00:00' + return fastTimeCreate(targetCalendar, 0, 0, 0); + } + + this.wasNullFlag = false; + + Field timeColField = this.fields[columnIndex - 1]; + + if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) { + // It's a timestamp + int length = timeAsString.length(); + + switch (length) { + case 19: { // YYYY-MM-DD hh:mm:ss + + hr = Integer.parseInt(timeAsString.substring(length - 8, + length - 6)); + min = Integer.parseInt(timeAsString.substring(length - 5, + length - 3)); + sec = Integer.parseInt(timeAsString.substring(length - 2, + length)); + } + + break; + case 14: + case 12: { + hr = Integer.parseInt(timeAsString.substring(length - 6, + length - 4)); + min = Integer.parseInt(timeAsString.substring(length - 4, + length - 2)); + sec = Integer.parseInt(timeAsString.substring(length - 2, + length)); + } + + break; + + case 10: { + hr = Integer.parseInt(timeAsString.substring(6, 8)); + min = Integer.parseInt(timeAsString.substring(8, 10)); + sec = 0; + } + + break; + + default: + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$ + + columnIndex + + "(" + + this.fields[columnIndex - 1] + ").", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } /* endswitch */ + + SQLWarning precisionLost = new SQLWarning( + Messages + .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$ + + columnIndex + + "(" + + this.fields[columnIndex - 1] + ")."); + + if (this.warningChain == null) { + this.warningChain = precisionLost; + } else { + this.warningChain.setNextWarning(precisionLost); + } + } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) { + hr = Integer.parseInt(timeAsString.substring(11, 13)); + min = Integer.parseInt(timeAsString.substring(14, 16)); + sec = Integer.parseInt(timeAsString.substring(17, 19)); + + SQLWarning precisionLost = new SQLWarning( + Messages + .getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$ + + columnIndex + + "(" + + this.fields[columnIndex - 1] + ")."); + + if (this.warningChain == null) { + this.warningChain = precisionLost; + } else { + this.warningChain.setNextWarning(precisionLost); + } + } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) { + return fastTimeCreate(targetCalendar, 0, 0, 0); // midnight on the given + // date + } else { + // convert a String to a Time + if ((timeAsString.length() != 5) + && (timeAsString.length() != 8)) { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$ + + timeAsString + + Messages.getString("ResultSet.___in_column__268") + + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + hr = Integer.parseInt(timeAsString.substring(0, 2)); + min = Integer.parseInt(timeAsString.substring(3, 5)); + sec = (timeAsString.length() == 5) ? 0 : Integer + .parseInt(timeAsString.substring(6)); + } + + Calendar sessionCalendar = this.getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + return TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + fastTimeCreate( + sessionCalendar, hr, min, sec), + this.connection.getServerTimezoneTZ(), + tz, rollForward); + } + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; + } + } + } + + /** + * Get the value of a column in the current row as a java.sql.Time object in + * the given timezone + * + * @param columnIndex + * the first column is 1, the second is 2... + * @param tz + * the Timezone to use + * + * @return the column value; null if SQL NULL + * + * @exception java.sql.SQLException + * if a database access error occurs + */ + private Time getTimeInternal(int columnIndex, Calendar targetCalendar, + TimeZone tz, + boolean rollForward) throws java.sql.SQLException { + checkRowPos(); + + if (this.isBinaryEncoded) { + return getNativeTime(columnIndex, targetCalendar, tz, rollForward); + } + + if (!this.useFastDateParsing) { + String timeAsString = getStringInternal(columnIndex, false); + + return getTimeFromString(timeAsString, targetCalendar, + columnIndex, tz, rollForward); + } + + checkColumnBounds(columnIndex); + + int columnIndexMinusOne = columnIndex - 1; + + if (this.thisRow.isNull(columnIndexMinusOne)) { + this.wasNullFlag = true; + + return null; + } + + this.wasNullFlag = false; + + return this.thisRow.getTimeFast(columnIndexMinusOne, + targetCalendar, tz, rollForward, this.connection, this); + } + + /** + * Get the value of a column in the current row as a java.sql.Timestamp + * object + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return the column value; null if SQL NULL + * + * @exception java.sql.SQLException + * if a database access error occurs + */ + public Timestamp getTimestamp(int columnIndex) throws java.sql.SQLException { + return getTimestampInternal(columnIndex, null, this.getDefaultTimeZone(), + false); + } + + /** + * Get the value of a column in the current row as a java.sql.Timestamp + * object. Use the calendar to construct an appropriate millisecond value + * for the Timestamp, if the underlying database doesn't store timezone + * information. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param cal + * the calendar to use in constructing the timestamp + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) + throws SQLException { + return getTimestampInternal(columnIndex, cal, cal.getTimeZone(), true); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws java.sql.SQLException + * DOCUMENT ME! + */ + public Timestamp getTimestamp(String columnName) + throws java.sql.SQLException { + return getTimestamp(findColumn(columnName)); + } + + /** + * Get the value of a column in the current row as a java.sql.Timestamp + * object. Use the calendar to construct an appropriate millisecond value + * for the Timestamp, if the underlying database doesn't store timezone + * information. + * + * @param columnName + * is the SQL name of the column + * @param cal + * the calendar to use in constructing the timestamp + * + * @return the column value; if the value is SQL NULL, the result is null + * + * @exception SQLException + * if a database-access error occurs. + */ + public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) + throws SQLException { + return getTimestamp(findColumn(columnName), cal); + } + + private Timestamp getTimestampFromString(int columnIndex, + Calendar targetCalendar, + String timestampValue, TimeZone tz, boolean rollForward) + throws java.sql.SQLException { + try { + this.wasNullFlag = false; + + if (timestampValue == null) { + this.wasNullFlag = true; + + return null; + } + + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + timestampValue = timestampValue.trim(); + + int length = timestampValue.length(); + + Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? + this.connection.getUtcCalendar() : + getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + if ((length > 0) + && (timestampValue.charAt(0) == '0') + && (timestampValue.equals("0000-00-00") + || timestampValue.equals("0000-00-00 00:00:00") + || timestampValue.equals("00000000000000") || timestampValue + .equals("0"))) { + + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(this.connection.getZeroDateTimeBehavior())) { + this.wasNullFlag = true; + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(this.connection.getZeroDateTimeBehavior())) { + throw SQLError.createSQLException("Value '" + timestampValue + + "' can not be represented as java.sql.Timestamp", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + // We're left with the case of 'round' to a date Java _can_ + // represent, which is '0001-01-01'. + return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0); + + } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { + + if (!this.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, Integer + .parseInt(timestampValue.substring(0, 4)), 1, + 1, 0, 0, 0, 0); + } + + return TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + fastTimestampCreate(sessionCalendar, + Integer + .parseInt(timestampValue.substring(0, 4)), 1, + 1, 0, 0, 0, 0), this.connection + .getServerTimezoneTZ(), tz, rollForward); + + } else { + if (timestampValue.endsWith(".")) { + timestampValue = timestampValue.substring(0, timestampValue + .length() - 1); + } + + // Convert from TIMESTAMP or DATE + + int year = 0; + int month = 0; + int day = 0; + int hour = 0; + int minutes = 0; + int seconds = 0; + int nanos = 0; + + switch (length) { + case 26: + case 25: + case 24: + case 23: + case 22: + case 21: + case 20: + case 19: { + year = Integer.parseInt(timestampValue.substring(0, 4)); + month = Integer + .parseInt(timestampValue.substring(5, 7)); + day = Integer.parseInt(timestampValue.substring(8, 10)); + hour = Integer.parseInt(timestampValue + .substring(11, 13)); + minutes = Integer.parseInt(timestampValue.substring(14, + 16)); + seconds = Integer.parseInt(timestampValue.substring(17, + 19)); + + nanos = 0; + + if (length > 19) { + int decimalIndex = timestampValue.lastIndexOf('.'); + + if (decimalIndex != -1) { + if ((decimalIndex + 2) <= length) { + nanos = Integer.parseInt(timestampValue + .substring(decimalIndex + 1)); + + int numDigits = length - (decimalIndex + 1); + + if (numDigits < 9) { + int factor = (int)(Math.pow(10, 9 - numDigits)); + nanos = nanos * factor; + } + } else { + throw new IllegalArgumentException(); // re-thrown + // further + // down + // with + // a + // much better error message + } + } + } + + break; + } + + case 14: { + year = Integer.parseInt(timestampValue.substring(0, 4)); + month = Integer + .parseInt(timestampValue.substring(4, 6)); + day = Integer.parseInt(timestampValue.substring(6, 8)); + hour = Integer + .parseInt(timestampValue.substring(8, 10)); + minutes = Integer.parseInt(timestampValue.substring(10, + 12)); + seconds = Integer.parseInt(timestampValue.substring(12, + 14)); + + break; + } + + case 12: { + year = Integer.parseInt(timestampValue.substring(0, 2)); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + + month = Integer + .parseInt(timestampValue.substring(2, 4)); + day = Integer.parseInt(timestampValue.substring(4, 6)); + hour = Integer.parseInt(timestampValue.substring(6, 8)); + minutes = Integer.parseInt(timestampValue.substring(8, + 10)); + seconds = Integer.parseInt(timestampValue.substring(10, + 12)); + + break; + } + + case 10: { + if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) + || (timestampValue.indexOf("-") != -1)) { + year = Integer.parseInt(timestampValue.substring(0, 4)); + month = Integer + .parseInt(timestampValue.substring(5, 7)); + day = Integer.parseInt(timestampValue.substring(8, 10)); + hour = 0; + minutes = 0; + } else { + year = Integer.parseInt(timestampValue.substring(0, 2)); + + if (year <= 69) { + year = (year + 100); + } + + month = Integer + .parseInt(timestampValue.substring(2, 4)); + day = Integer.parseInt(timestampValue.substring(4, 6)); + hour = Integer.parseInt(timestampValue.substring(6, 8)); + minutes = Integer.parseInt(timestampValue.substring(8, + 10)); + + year += 1900; // two-digit year + } + + break; + } + + case 8: { + if (timestampValue.indexOf(":") != -1) { + hour = Integer.parseInt(timestampValue.substring(0, + 2)); + minutes = Integer.parseInt(timestampValue + .substring(3, 5)); + seconds = Integer.parseInt(timestampValue + .substring(6, 8)); + year = 1970; + month = 1; + day = 1; + break; + } + + year = Integer.parseInt(timestampValue.substring(0, 4)); + month = Integer + .parseInt(timestampValue.substring(4, 6)); + day = Integer.parseInt(timestampValue.substring(6, 8)); + + year -= 1900; + month--; + + break; + } + + case 6: { + year = Integer.parseInt(timestampValue.substring(0, 2)); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + + month = Integer + .parseInt(timestampValue.substring(2, 4)); + day = Integer.parseInt(timestampValue.substring(4, 6)); + + break; + } + + case 4: { + year = Integer.parseInt(timestampValue.substring(0, 2)); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + + month = Integer + .parseInt(timestampValue.substring(2, 4)); + + day = 1; + + break; + } + + case 2: { + year = Integer.parseInt(timestampValue.substring(0, 2)); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + month = 1; + day = 1; + + break; + } + + default: + throw new java.sql.SQLException( + "Bad format for Timestamp '" + timestampValue + + "' in column " + columnIndex + ".", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + } + + if (!this.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, year, month, day, hour, + minutes, seconds, nanos); + } + + return TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + fastTimestampCreate(sessionCalendar, year, month, day, hour, + minutes, seconds, nanos), this.connection + .getServerTimezoneTZ(), tz, rollForward); + } + } + } catch (RuntimeException e) { + SQLException sqlEx = SQLError.createSQLException("Cannot convert value '" + + timestampValue + "' from column " + columnIndex + + " to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } + + } + + /** + * Get the value of a column in the current row as a java.sql.Timestamp + * object in the given timezone + * + * @param columnIndex + * the first column is 1, the second is 2... + * @param tz + * the timezone to use + * + * @return the column value; null if SQL NULL + * + * @exception java.sql.SQLException + * if a database access error occurs + */ + private Timestamp getTimestampInternal(int columnIndex, Calendar targetCalendar, + TimeZone tz, + boolean rollForward) throws java.sql.SQLException { + if (this.isBinaryEncoded) { + return getNativeTimestamp(columnIndex, targetCalendar, tz, rollForward); + } + + Timestamp tsVal = null; + + if (!this.useFastDateParsing) { + String timestampValue = getStringInternal(columnIndex, false); + + tsVal = getTimestampFromString(columnIndex, targetCalendar, + timestampValue, tz, + rollForward); + } else { + checkClosed(); + checkRowPos(); + checkColumnBounds(columnIndex); + + tsVal = this.thisRow.getTimestampFast(columnIndex - 1, + targetCalendar, tz, rollForward, this.connection, this); + } + + if (tsVal == null) { + this.wasNullFlag = true; + } else { + this.wasNullFlag = false; + } + + return tsVal; + } + + /** + * JDBC 2.0 Return the type of this result set. The type is determined based + * on the statement that created the result set. + * + * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or + * TYPE_SCROLL_SENSITIVE + * + * @exception SQLException + * if a database-access error occurs + */ + public int getType() throws SQLException { + return this.resultSetType; + } + + /** + * A column value can also be retrieved as a stream of Unicode characters. + * We implement this as a binary stream. + * + * @param columnIndex + * the first column is 1, the second is 2... + * + * @return a Java InputStream that delivers the database column value as a + * stream of two byte Unicode characters. If the value is SQL NULL, + * then the result is null + * + * @exception SQLException + * if a database access error occurs + * + * @see getAsciiStream + * @see getBinaryStream + * @deprecated + */ + public InputStream getUnicodeStream(int columnIndex) throws SQLException { + if (!this.isBinaryEncoded) { + checkRowPos(); + + return getBinaryStream(columnIndex); + } + + return getNativeBinaryStream(columnIndex); + } + + /** + * DOCUMENT ME! + * + * @param columnName + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + * + * @deprecated + */ + public InputStream getUnicodeStream(String columnName) throws SQLException { + return getUnicodeStream(findColumn(columnName)); + } + + public long getUpdateCount() { + return this.updateCount; + } + + public long getUpdateID() { + return this.updateId; + } + + /** + * @see ResultSetInternalMethods#getURL(int) + */ + public URL getURL(int colIndex) throws SQLException { + String val = getString(colIndex); + + if (val == null) { + return null; + } + + try { + return new URL(val); + } catch (MalformedURLException mfe) { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Malformed_URL____104") + + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * @see ResultSetInternalMethods#getURL(String) + */ + public URL getURL(String colName) throws SQLException { + String val = getString(colName); + + if (val == null) { + return null; + } + + try { + return new URL(val); + } catch (MalformedURLException mfe) { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Malformed_URL____107") + + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * The first warning reported by calls on this ResultSet is returned. + * Subsequent ResultSet warnings will be chained to this + * java.sql.SQLWarning. + * + *

+ * The warning chain is automatically cleared each time a new row is read. + *

+ * + *

+ * Note: This warning chain only covers warnings caused by ResultSet + * methods. Any warnings caused by statement methods (such as reading OUT + * parameters) will be chained on the Statement object. + *

+ * + * @return the first java.sql.SQLWarning or null; + * + * @exception SQLException + * if a database access error occurs. + */ + public java.sql.SQLWarning getWarnings() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.warningChain; + } + } + + /** + * JDBC 2.0 Insert the contents of the insert row into the result set and + * the database. Must be on the insert row when this method is called. + * + * @exception SQLException + * if a database-access error occurs, if called when not on + * the insert row, or if all non-nullable columns in the + * insert row have not been given a value + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void insertRow() throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 + * + *

+ * Determine if the cursor is after the last row in the result set. + *

+ * + * @return true if after the last row, false otherwise. Returns false when + * the result set contains no rows. + * + * @exception SQLException + * if a database-access error occurs. + */ + public boolean isAfterLast() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + boolean b = this.rowData.isAfterLast(); + + return b; + } + } + + /** + * JDBC 2.0 + * + *

+ * Determine if the cursor is before the first row in the result set. + *

+ * + * @return true if before the first row, false otherwise. Returns false when + * the result set contains no rows. + * + * @exception SQLException + * if a database-access error occurs. + */ + public boolean isBeforeFirst() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.rowData.isBeforeFirst(); + } + } + + /** + * JDBC 2.0 + * + *

+ * Determine if the cursor is on the first row of the result set. + *

+ * + * @return true if on the first row, false otherwise. + * + * @exception SQLException + * if a database-access error occurs. + */ + public boolean isFirst() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.rowData.isFirst(); + } + } + + /** + * JDBC 2.0 + * + *

+ * Determine if the cursor is on the last row of the result set. Note: + * Calling isLast() may be expensive since the JDBC driver might need to + * fetch ahead one row in order to determine whether the current row is the + * last row in the result set. + *

+ * + * @return true if on the last row, false otherwise. + * + * @exception SQLException + * if a database-access error occurs. + */ + public boolean isLast() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.rowData.isLast(); + } + } + + /** + * @param string + * @param mysqlType + * @param s + */ + private void issueConversionViaParsingWarning(String methodName, + int columnIndex, Object value, Field fieldInfo, + int[] typesWithNoParseConversion) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + StringBuffer originalQueryBuf = new StringBuffer(); + + if (this.owningStatement != null + && this.owningStatement instanceof com.mysql.jdbc.PreparedStatement) { + originalQueryBuf.append(Messages.getString("ResultSet.CostlyConversionCreatedFromQuery")); + originalQueryBuf + .append(((com.mysql.jdbc.PreparedStatement) this.owningStatement).originalSql); + originalQueryBuf.append("\n\n"); + } else { + originalQueryBuf.append("."); + } + + StringBuffer convertibleTypesBuf = new StringBuffer(); + + for (int i = 0; i < typesWithNoParseConversion.length; i++) { + convertibleTypesBuf.append(MysqlDefs.typeToName(typesWithNoParseConversion[i])); + convertibleTypesBuf.append("\n"); + } + + String message = Messages.getString("ResultSet.CostlyConversion", new Object[] { + methodName, + Integer.valueOf(columnIndex + 1), + fieldInfo.getOriginalName(), + fieldInfo.getOriginalTableName(), + originalQueryBuf.toString(), + value != null ? value.getClass().getName() : ResultSetMetaData.getClassNameForJavaType( + fieldInfo.getSQLType(), + fieldInfo.isUnsigned(), + fieldInfo.getMysqlType(), + fieldInfo.isBinary() || fieldInfo.isBlob(), + fieldInfo.isOpaqueBinary(), + connection.getYearIsDateType()), + MysqlDefs.typeToName(fieldInfo.getMysqlType()), + convertibleTypesBuf.toString()}); + + this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, + "", (this.owningStatement == null) ? "N/A" + : this.owningStatement.currentCatalog, + this.connectionId, (this.owningStatement == null) ? (-1) + : this.owningStatement.getId(), this.resultId, System + .currentTimeMillis(), 0, Constants.MILLIS_I18N, null, + this.pointOfOrigin, message)); + } + } + + /** + * JDBC 2.0 + * + *

+ * Moves to the last row in the result set. + *

+ * + * @return true if on a valid row, false if no rows in the result set. + * + * @exception SQLException + * if a database-access error occurs, or result set type is + * TYPE_FORWARD_ONLY. + */ + public boolean last() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + boolean b = true; + + if (this.rowData.size() == 0) { + b = false; + } else { + + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + this.rowData.beforeLast(); + this.thisRow = this.rowData.next(); + } + + setRowPositionValidity(); + + return b; + } + } + + // ///////////////////////////////////////// + // + // These number conversion routines save + // a ton of "new()s", especially for the heavily + // used getInt() and getDouble() methods + // + // ///////////////////////////////////////// + + /** + * JDBC 2.0 Move the cursor to the remembered cursor position, usually the + * current row. Has no effect unless the cursor is on the insert row. + * + * @exception SQLException + * if a database-access error occurs, or the result set is + * not updatable + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void moveToCurrentRow() throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Move to the insert row. The current cursor position is + * remembered while the cursor is positioned on the insert row. The insert + * row is a special row associated with an updatable result set. It is + * essentially a buffer where a new row may be constructed by calling the + * updateXXX() methods prior to inserting the row into the result set. Only + * the updateXXX(), getXXX(), and insertRow() methods may be called when the + * cursor is on the insert row. All of the columns in a result set must be + * given a value each time this method is called before calling insertRow(). + * UpdateXXX()must be called before getXXX() on a column. + * + * @exception SQLException + * if a database-access error occurs, or the result set is + * not updatable + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void moveToInsertRow() throws SQLException { + throw new NotUpdatable(); + } + + /** + * A ResultSet is initially positioned before its first row, the first call + * to next makes the first row the current row; the second call makes the + * second row the current row, etc. + * + *

+ * If an input stream from the previous row is open, it is implicitly + * closed. The ResultSet's warning chain is cleared when a new row is read + *

+ * + * @return true if the new current is valid; false if there are no more rows + * + * @exception SQLException + * if a database access error occurs + */ + public boolean next() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + boolean b; + + if (!reallyResult()) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.ResultSet_is_from_UPDATE._No_Data_115"), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); //$NON-NLS-1$ + } + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + if (this.rowData.size() == 0) { + b = false; + } else { + this.thisRow = this.rowData.next(); + + if (this.thisRow == null) { + b = false; + } else { + clearWarnings(); + + b = true; + + } + } + + setRowPositionValidity(); + + return b; + } + } + + private int parseIntAsDouble(int columnIndex, String val) + throws NumberFormatException, SQLException { + if (val == null) { + return 0; + } + + double valueAsDouble = Double.parseDouble(val); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Integer.MIN_VALUE + || valueAsDouble > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), columnIndex, + Types.INTEGER); + } + } + + return (int) valueAsDouble; + } + + private int getIntWithOverflowCheck(int columnIndex) throws SQLException { + int intValue = this.thisRow.getInt(columnIndex); + + checkForIntegerTruncation(columnIndex, + null, intValue); + + return intValue; + } + + private void checkForIntegerTruncation(int columnIndex, + byte[] valueAsBytes, int intValue) + throws SQLException { + if (this.jdbcCompliantTruncationForReads) { + if (intValue == Integer.MIN_VALUE || intValue == Integer.MAX_VALUE) { + String valueAsString = null; + + if (valueAsBytes == null) { + valueAsString = this.thisRow.getString( + columnIndex, this.fields[columnIndex].getCharacterSet(), + this.connection); + } + + long valueAsLong = Long + .parseLong(valueAsString == null ? StringUtils.toString( + valueAsBytes) : valueAsString); + + if (valueAsLong < Integer.MIN_VALUE + || valueAsLong > Integer.MAX_VALUE) { + throwRangeException(valueAsString == null ? StringUtils.toString( + valueAsBytes) : valueAsString, columnIndex + 1, + Types.INTEGER); + } + } + } + } + + private long parseLongAsDouble(int columnIndexZeroBased, String val) + throws NumberFormatException, SQLException { + if (val == null) { + return 0; + } + + double valueAsDouble = Double.parseDouble(val); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Long.MIN_VALUE + || valueAsDouble > Long.MAX_VALUE) { + throwRangeException(val, columnIndexZeroBased + 1, Types.BIGINT); + } + } + + return (long) valueAsDouble; + } + + private long getLongWithOverflowCheck(int columnIndexZeroBased, boolean doOverflowCheck) throws SQLException { + long longValue = this.thisRow.getLong(columnIndexZeroBased); + + if (doOverflowCheck) { + checkForLongTruncation(columnIndexZeroBased, null, longValue); + } + + return longValue; + } + + private long parseLongWithOverflowCheck(int columnIndexZeroBased, + byte[] valueAsBytes, String valueAsString, boolean doCheck) + throws NumberFormatException, SQLException { + + long longValue = 0; + + if (valueAsBytes == null && valueAsString == null) { + return 0; + } + + if (valueAsBytes != null) { + longValue = StringUtils.getLong(valueAsBytes); + } else { + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + valueAsString = valueAsString.trim(); + + longValue = Long.parseLong(valueAsString); + } + + if (doCheck && this.jdbcCompliantTruncationForReads) { + checkForLongTruncation(columnIndexZeroBased, valueAsBytes, longValue); + } + + return longValue; + } + + private void checkForLongTruncation(int columnIndexZeroBased, byte[] valueAsBytes, long longValue) throws SQLException { + if (longValue == Long.MIN_VALUE + || longValue == Long.MAX_VALUE) { + String valueAsString = null; + + if (valueAsBytes == null) { + valueAsString = this.thisRow.getString( + columnIndexZeroBased, this.fields[columnIndexZeroBased].getCharacterSet(), + this.connection); + } + + double valueAsDouble = Double + .parseDouble(valueAsString == null ? StringUtils.toString( + valueAsBytes) : valueAsString); + + if (valueAsDouble < Long.MIN_VALUE + || valueAsDouble > Long.MAX_VALUE) { + throwRangeException(valueAsString == null ? StringUtils.toString( + valueAsBytes) : valueAsString, columnIndexZeroBased + 1, + Types.BIGINT); + } + } + } + + private short parseShortAsDouble(int columnIndex, String val) + throws NumberFormatException, SQLException { + if (val == null) { + return 0; + } + + double valueAsDouble = Double.parseDouble(val); + + if (this.jdbcCompliantTruncationForReads) { + if (valueAsDouble < Short.MIN_VALUE + || valueAsDouble > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), columnIndex, + Types.SMALLINT); + } + } + + return (short) valueAsDouble; + } + + private short parseShortWithOverflowCheck(int columnIndex, + byte[] valueAsBytes, String valueAsString) + throws NumberFormatException, SQLException { + + short shortValue = 0; + + if (valueAsBytes == null && valueAsString == null) { + return 0; + } + + if (valueAsBytes != null) { + shortValue = StringUtils.getShort(valueAsBytes); + } else { + // + // JDK-6 doesn't like trailing whitespace + // + // Note this isn't a performance issue, other + // than the iteration over the string, as String.trim() + // will return a new string only if whitespace is present + // + + valueAsString = valueAsString.trim(); + + shortValue = Short.parseShort(valueAsString); + } + + if (this.jdbcCompliantTruncationForReads) { + if (shortValue == Short.MIN_VALUE || shortValue == Short.MAX_VALUE) { + long valueAsLong = Long + .parseLong(valueAsString == null ? StringUtils.toString( + valueAsBytes) : valueAsString); + + if (valueAsLong < Short.MIN_VALUE + || valueAsLong > Short.MAX_VALUE) { + throwRangeException(valueAsString == null ? StringUtils.toString( + valueAsBytes) : valueAsString, columnIndex, + Types.SMALLINT); + } + } + } + + return shortValue; + } + + // --------------------------JDBC 2.0----------------------------------- + // --------------------------------------------------------------------- + // Getter's and Setter's + // --------------------------------------------------------------------- + + /** + * The prev method is not part of JDBC, but because of the architecture of + * this driver it is possible to move both forward and backward within the + * result set. + * + *

+ * If an input stream from the previous row is open, it is implicitly + * closed. The ResultSet's warning chain is cleared when a new row is read + *

+ * + * @return true if the new current is valid; false if there are no more rows + * + * @exception java.sql.SQLException + * if a database access error occurs + */ + public boolean prev() throws java.sql.SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + int rowIndex = this.rowData.getCurrentRowNumber(); + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + boolean b = true; + + if ((rowIndex - 1) >= 0) { + rowIndex--; + this.rowData.setCurrentRow(rowIndex); + this.thisRow = this.rowData.getAt(rowIndex); + + b = true; + } else if ((rowIndex - 1) == -1) { + rowIndex--; + this.rowData.setCurrentRow(rowIndex); + this.thisRow = null; + + b = false; + } else { + b = false; + } + + setRowPositionValidity(); + + return b; + } + } + + /** + * JDBC 2.0 + * + *

+ * Moves to the previous row in the result set. + *

+ * + *

+ * Note: previous() is not the same as relative(-1) since it makes sense to + * call previous() when there is no current row. + *

+ * + * @return true if on a valid row, false if off the result set. + * + * @exception SQLException + * if a database-access error occurs, or result set type is + * TYPE_FORWAR_DONLY. + */ + public boolean previous() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.onInsertRow) { + this.onInsertRow = false; + } + + if (this.doingUpdates) { + this.doingUpdates = false; + } + + return prev(); + } + } + + /** + * Closes this ResultSet and releases resources. + * + * @param calledExplicitly + * was realClose called by the standard ResultSet.close() method, or was it closed internally by the + * driver? + * + * @throws SQLException + * if an error occurs + */ + public void realClose(boolean calledExplicitly) throws SQLException { + MySQLConnection locallyScopedConn = this.connection; + + if (locallyScopedConn == null) return; // already closed + + synchronized (locallyScopedConn.getConnectionMutex()) { + + // additional check in case ResultSet was closed + // while current thread was waiting for lock + if (this.isClosed) return; + + try { + if (this.useUsageAdvisor) { + + // Report on result set closed by driver instead of application + + if (!calledExplicitly) { + this.eventSink + .consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, + "", + (this.owningStatement == null) ? "N/A" + : this.owningStatement.currentCatalog, + this.connectionId, + (this.owningStatement == null) ? (-1) + : this.owningStatement.getId(), + this.resultId, + System.currentTimeMillis(), + 0, + Constants.MILLIS_I18N, + null, + this.pointOfOrigin, + Messages + .getString("ResultSet.ResultSet_implicitly_closed_by_driver"))); //$NON-NLS-1$ + } + + if (this.rowData instanceof RowDataStatic) { + + // Report on possibly too-large result sets + + if (this.rowData.size() > this.connection + .getResultSetSizeThreshold()) { + this.eventSink + .consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, + "", + (this.owningStatement == null) ? Messages + .getString("ResultSet.N/A_159") + : this.owningStatement.currentCatalog, //$NON-NLS-1$ + this.connectionId, + (this.owningStatement == null) ? (-1) + : this.owningStatement.getId(), + this.resultId, + System.currentTimeMillis(), + 0, + Constants.MILLIS_I18N, + null, + this.pointOfOrigin, + Messages + .getString( + "ResultSet.Too_Large_Result_Set", + new Object[] { + Integer.valueOf( + this.rowData + .size()), + Integer.valueOf( + this.connection + .getResultSetSizeThreshold()) }))); + } + + if (!isLast() && !isAfterLast() && (this.rowData.size() != 0)) { + + this.eventSink + .consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, + "", + (this.owningStatement == null) ? Messages + .getString("ResultSet.N/A_159") + : this.owningStatement.currentCatalog, //$NON-NLS-1$ + this.connectionId, + (this.owningStatement == null) ? (-1) + : this.owningStatement.getId(), + this.resultId, + System.currentTimeMillis(), + 0, + Constants.MILLIS_I18N, + null, + this.pointOfOrigin, + Messages + .getString( + "ResultSet.Possible_incomplete_traversal_of_result_set", //$NON-NLS-1$ + new Object[] { + Integer.valueOf( + getRow()), + Integer.valueOf( + this.rowData + .size()) }))); + } + } + + // + // Report on any columns that were selected but + // not referenced + // + + if (this.columnUsed.length > 0 && !this.rowData.wasEmpty()) { + StringBuffer buf = new StringBuffer( + Messages + .getString("ResultSet.The_following_columns_were_never_referenced")); //$NON-NLS-1$ + + boolean issueWarn = false; + + for (int i = 0; i < this.columnUsed.length; i++) { + if (!this.columnUsed[i]) { + if (!issueWarn) { + issueWarn = true; + } else { + buf.append(", "); + } + + buf.append(this.fields[i].getFullName()); + } + } + + if (issueWarn) { + this.eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, "", + (this.owningStatement == null) ? "N/A" + : this.owningStatement.currentCatalog, + this.connectionId, + (this.owningStatement == null) ? (-1) + : this.owningStatement.getId(), 0, + System.currentTimeMillis(), 0, + Constants.MILLIS_I18N, null, + this.pointOfOrigin, buf.toString())); + } + } + } + } finally { + if (this.owningStatement != null && calledExplicitly) { + this.owningStatement.removeOpenResultSet(this); + } + + SQLException exceptionDuringClose = null; + + if (this.rowData != null) { + try { + this.rowData.close(); + } catch (SQLException sqlEx) { + exceptionDuringClose = sqlEx; + } + } + + if (this.statementUsedForFetchingRows != null) { + try { + this.statementUsedForFetchingRows.realClose(true, false); + } catch (SQLException sqlEx) { + if (exceptionDuringClose != null) { + exceptionDuringClose.setNextException(sqlEx); + } else { + exceptionDuringClose = sqlEx; + } + } + } + + this.rowData = null; + this.defaultTimeZone = null; + this.fields = null; + this.columnLabelToIndex = null; + this.fullColumnNameToIndex = null; + this.columnToIndexCache = null; + this.eventSink = null; + this.warningChain = null; + + if (!this.retainOwningStatement) { + this.owningStatement = null; + } + + this.catalog = null; + this.serverInfo = null; + this.thisRow = null; + this.fastDateCal = null; + this.connection = null; + + this.isClosed = true; + + if (exceptionDuringClose != null) { + throw exceptionDuringClose; + } + } + } + } + + /** + * Returns true if this ResultSet is closed. + */ + public boolean isClosed() throws SQLException { + return this.isClosed; + } + + public boolean reallyResult() { + if (this.rowData != null) { + return true; + } + + return this.reallyResult; + } + + /** + * JDBC 2.0 Refresh the value of the current row with its current value in + * the database. Cannot be called when on the insert row. The refreshRow() + * method provides a way for an application to explicitly tell the JDBC + * driver to refetch a row(s) from the database. An application may want to + * call refreshRow() when caching or prefetching is being done by the JDBC + * driver to fetch the latest value of a row from the database. The JDBC + * driver may actually refresh multiple rows at once if the fetch size is + * greater than one. All values are refetched subject to the transaction + * isolation level and cursor sensitivity. If refreshRow() is called after + * calling updateXXX(), but before calling updateRow() then the updates made + * to the row are lost. Calling refreshRow() frequently will likely slow + * performance. + * + * @exception SQLException + * if a database-access error occurs, or if called when on + * the insert row. + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void refreshRow() throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 + * + *

+ * Moves a relative number of rows, either positive or negative. Attempting + * to move beyond the first/last row in the result set positions the cursor + * before/after the the first/last row. Calling relative(0) is valid, but + * does not change the cursor position. + *

+ * + *

+ * Note: Calling relative(1) is different than calling next() since is makes + * sense to call next() when there is no current row, for example, when the + * cursor is positioned before the first row or after the last row of the + * result set. + *

+ * + * @param rows + * the number of relative rows to move the cursor. + * + * @return true if on a row, false otherwise. + * + * @throws SQLException + * if a database-access error occurs, or there is no current + * row, or result set type is TYPE_FORWARD_ONLY. + */ + public boolean relative(int rows) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + if (this.rowData.size() == 0) { + setRowPositionValidity(); + + return false; + } + + if (this.thisRow != null) { + this.thisRow.closeOpenStreams(); + } + + this.rowData.moveRowRelative(rows); + this.thisRow = this.rowData.getAt(this.rowData.getCurrentRowNumber()); + + setRowPositionValidity(); + + return (!this.rowData.isAfterLast() && !this.rowData.isBeforeFirst()); + } + } + + /** + * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave + * a visible "hole" in a result set. This method can be used to detect holes + * in a result set. The value returned depends on whether or not the result + * set can detect deletions. + * + * @return true if deleted and deletes are detected + * + * @exception SQLException + * if a database-access error occurs + * @throws NotImplemented + * DOCUMENT ME! + * + * @see DatabaseMetaData#deletesAreDetected + */ + public boolean rowDeleted() throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * JDBC 2.0 Determine if the current row has been inserted. The value + * returned depends on whether or not the result set can detect visible + * inserts. + * + * @return true if inserted and inserts are detected + * + * @exception SQLException + * if a database-access error occurs + * @throws NotImplemented + * DOCUMENT ME! + * + * @see DatabaseMetaData#insertsAreDetected + */ + public boolean rowInserted() throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * JDBC 2.0 Determine if the current row has been updated. The value + * returned depends on whether or not the result set can detect updates. + * + * @return true if the row has been visibly updated by the owner or another, + * and updates are detected + * + * @exception SQLException + * if a database-access error occurs + * @throws NotImplemented + * DOCUMENT ME! + * + * @see DatabaseMetaData#updatesAreDetected + */ + public boolean rowUpdated() throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * Flag that this result set is 'binary' encoded (from a PreparedStatement), + * not stored as strings. + */ + protected void setBinaryEncoded() { + this.isBinaryEncoded = true; + } + + private void setDefaultTimeZone(TimeZone defaultTimeZone) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.defaultTimeZone = defaultTimeZone; + } + } + + /** + * JDBC 2.0 Give a hint as to the direction in which the rows in this result + * set will be processed. The initial value is determined by the statement + * that produced the result set. The fetch direction may be changed at any + * time. + * + * @param direction + * the direction to fetch rows in. + * + * @exception SQLException + * if a database-access error occurs, or the result set type + * is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD. + * MM.MySQL actually ignores this, because it has the whole + * result set anyway, so the direction is immaterial. + */ + public void setFetchDirection(int direction) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE) + && (direction != FETCH_UNKNOWN)) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Illegal_value_for_fetch_direction_64"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + this.fetchDirection = direction; + } + } + + /** + * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should + * be fetched from the database when more rows are needed for this result + * set. If the fetch size specified is zero, then the JDBC driver ignores + * the value, and is free to make its own best guess as to what the fetch + * size should be. The default value is set by the statement that creates + * the result set. The fetch size may be changed at any time. + * + * @param rows + * the number of rows to fetch + * + * @exception SQLException + * if a database-access error occurs, or the condition 0 lteq + * rows lteq this.getMaxRows() is not satisfied. Currently + * ignored by this driver. + */ + public void setFetchSize(int rows) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (rows < 0) { /* || rows > getMaxRows() */ + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Value_must_be_between_0_and_getMaxRows()_66"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + this.fetchSize = rows; + } + } + + /** + * Sets the first character of the query that this result set was created + * from. + * + * @param c + * the first character of the query...uppercased + */ + public void setFirstCharOfQuery(char c) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.firstCharOfQuery = c; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + /** + * DOCUMENT ME! + * + * @param nextResultSet + * Sets the next result set in the result set chain for multiple + * result sets. + */ + protected synchronized void setNextResultSet(ResultSetInternalMethods nextResultSet) { + this.nextResultSet = nextResultSet; + } + + public void setOwningStatement(com.mysql.jdbc.StatementImpl owningStatement) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.owningStatement = owningStatement; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + /** + * Sets the concurrency (JDBC2) + * + * @param concurrencyFlag + * CONCUR_UPDATABLE or CONCUR_READONLY + */ + protected synchronized void setResultSetConcurrency(int concurrencyFlag) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.resultSetConcurrency = concurrencyFlag; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + /** + * Sets the result set type for (JDBC2) + * + * @param typeFlag + * SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support + * SCROLL_INSENSITIVE) + */ + protected synchronized void setResultSetType(int typeFlag) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.resultSetType = typeFlag; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + /** + * Sets server info (if any) + * + * @param info + * the server info message + */ + protected synchronized void setServerInfo(String info) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.serverInfo = info; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + public synchronized void setStatementUsedForFetchingRows(PreparedStatement stmt) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.statementUsedForFetchingRows = stmt; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + /** + * @param wrapperStatement + * The wrapperStatement to set. + */ + public synchronized void setWrapperStatement(java.sql.Statement wrapperStatement) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.wrapperStatement = wrapperStatement; + } + } catch (SQLException e) { + throw new RuntimeException(e); // FIXME: Need to evolve public interface + } + } + + private void throwRangeException(String valueAsString, int columnIndex, + int jdbcType) throws SQLException { + String datatype = null; + + switch (jdbcType) { + case Types.TINYINT: + datatype = "TINYINT"; + break; + case Types.SMALLINT: + datatype = "SMALLINT"; + break; + case Types.INTEGER: + datatype = "INTEGER"; + break; + case Types.BIGINT: + datatype = "BIGINT"; + break; + case Types.REAL: + datatype = "REAL"; + break; + case Types.FLOAT: + datatype = "FLOAT"; + break; + case Types.DOUBLE: + datatype = "DOUBLE"; + break; + case Types.DECIMAL: + datatype = "DECIMAL"; + break; + default: + datatype = " (JDBC type '" + jdbcType + "')"; + } + + throw SQLError.createSQLException("'" + valueAsString + "' in column '" + + columnIndex + "' is outside valid range for the datatype " + + datatype + ".", SQLError.SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE, getExceptionInterceptor()); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String toString() { + if (this.reallyResult) { + return super.toString(); + } + + return "Result set representing update count of " + this.updateCount; + } + + /** + * @see ResultSetInternalMethods#updateArray(int, Array) + */ + public void updateArray(int arg0, Array arg1) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * @see ResultSetInternalMethods#updateArray(String, Array) + */ + public void updateArray(String arg0, Array arg1) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * JDBC 2.0 Update a column with an ascii stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param length + * the length of the stream + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateAsciiStream(int columnIndex, java.io.InputStream x, + int length) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with an ascii stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * @param length + * of the stream + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateAsciiStream(String columnName, java.io.InputStream x, + int length) throws SQLException { + updateAsciiStream(findColumn(columnName), x, length); + } + + /** + * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateBigDecimal(int columnIndex, BigDecimal x) + throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateBigDecimal(String columnName, BigDecimal x) + throws SQLException { + updateBigDecimal(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a binary stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param length + * the length of the stream + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateBinaryStream(int columnIndex, java.io.InputStream x, + int length) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a binary stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * @param length + * of the stream + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateBinaryStream(String columnName, java.io.InputStream x, + int length) throws SQLException { + updateBinaryStream(findColumn(columnName), x, length); + } + + /** + * @see ResultSetInternalMethods#updateBlob(int, Blob) + */ + public void updateBlob(int arg0, java.sql.Blob arg1) throws SQLException { + throw new NotUpdatable(); + } + + /** + * @see ResultSetInternalMethods#updateBlob(String, Blob) + */ + public void updateBlob(String arg0, java.sql.Blob arg1) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateBoolean(int columnIndex, boolean x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateBoolean(String columnName, boolean x) throws SQLException { + updateBoolean(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateByte(int columnIndex, byte x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateByte(String columnName, byte x) throws SQLException { + updateByte(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateBytes(int columnIndex, byte[] x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateBytes(String columnName, byte[] x) throws SQLException { + updateBytes(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a character stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param length + * the length of the stream + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateCharacterStream(int columnIndex, java.io.Reader x, + int length) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a character stream value. The updateXXX() + * methods are used to update column values in the current row, or the + * insert row. The updateXXX() methods do not update the underlying + * database, instead the updateRow() or insertRow() methods are called to + * update the database. + * + * @param columnName + * the name of the column + * @param reader + * the stream to update the column with + * @param length + * of the stream + * + * @throws SQLException + * if a database-access error occurs + */ + public void updateCharacterStream(String columnName, java.io.Reader reader, + int length) throws SQLException { + updateCharacterStream(findColumn(columnName), reader, length); + } + + /** + * @see ResultSetInternalMethods#updateClob(int, Clob) + */ + public void updateClob(int arg0, java.sql.Clob arg1) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * @see ResultSetInternalMethods#updateClob(String, Clob) + */ + public void updateClob(String columnName, java.sql.Clob clob) + throws SQLException { + updateClob(findColumn(columnName), clob); + } + + /** + * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateDate(int columnIndex, java.sql.Date x) + throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateDate(String columnName, java.sql.Date x) + throws SQLException { + updateDate(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateDouble(int columnIndex, double x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a double value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateDouble(String columnName, double x) throws SQLException { + updateDouble(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a float value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateFloat(int columnIndex, float x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a float value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateFloat(String columnName, float x) throws SQLException { + updateFloat(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with an integer value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateInt(int columnIndex, int x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with an integer value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateInt(String columnName, int x) throws SQLException { + updateInt(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a long value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateLong(int columnIndex, long x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a long value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateLong(String columnName, long x) throws SQLException { + updateLong(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateNull(int columnIndex) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a null value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateNull(String columnName) throws SQLException { + updateNull(findColumn(columnName)); + } + + /** + * JDBC 2.0 Update a column with an Object value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateObject(int columnIndex, Object x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with an Object value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * @param scale + * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types + * this is the number of digits after the decimal. For all other + * types this value will be ignored. + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateObject(int columnIndex, Object x, int scale) + throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with an Object value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateObject(String columnName, Object x) throws SQLException { + updateObject(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with an Object value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * @param scale + * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types + * this is the number of digits after the decimal. For all other + * types this value will be ignored. + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateObject(String columnName, Object x, int scale) + throws SQLException { + updateObject(findColumn(columnName), x); + } + + /** + * @see ResultSetInternalMethods#updateRef(int, Ref) + */ + public void updateRef(int arg0, Ref arg1) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * @see ResultSetInternalMethods#updateRef(String, Ref) + */ + public void updateRef(String arg0, Ref arg1) throws SQLException { + throw SQLError.notImplemented(); + } + + /** + * JDBC 2.0 Update the underlying database with the new contents of the + * current row. Cannot be called when on the insert row. + * + * @exception SQLException + * if a database-access error occurs, or if called when on + * the insert row + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateRow() throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a short value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateShort(int columnIndex, short x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a short value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateShort(String columnName, short x) throws SQLException { + updateShort(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a String value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateString(int columnIndex, String x) throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a String value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateString(String columnName, String x) throws SQLException { + updateString(findColumn(columnName), x); + } + + /** + * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateTime(int columnIndex, java.sql.Time x) + throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are + * used to update column values in the current row, or the insert row. The + * updateXXX() methods do not update the underlying database, instead the + * updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateTime(String columnName, java.sql.Time x) + throws SQLException { + updateTime(findColumn(columnName), x); + } + + + /** + * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnIndex + * the first column is 1, the second is 2, ... + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + * @throws NotUpdatable + * DOCUMENT ME! + */ + public void updateTimestamp(int columnIndex, java.sql.Timestamp x) + throws SQLException { + throw new NotUpdatable(); + } + + /** + * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods + * are used to update column values in the current row, or the insert row. + * The updateXXX() methods do not update the underlying database, instead + * the updateRow() or insertRow() methods are called to update the database. + * + * @param columnName + * the name of the column + * @param x + * the new column value + * + * @exception SQLException + * if a database-access error occurs + */ + public void updateTimestamp(String columnName, java.sql.Timestamp x) + throws SQLException { + updateTimestamp(findColumn(columnName), x); + } + + /** + * A column may have the value of SQL NULL; wasNull() reports whether the + * last column read had this special value. Note that you must first call + * getXXX on a column to try to read its value and then call wasNull() to + * find if the value was SQL NULL + * + * @return true if the last column read was SQL NULL + * + * @exception SQLException + * if a database access error occurred + */ + public boolean wasNull() throws SQLException { + return this.wasNullFlag; + } + + protected Calendar getGmtCalendar() { + + // Worst case we allocate this twice and the other gets GC'd, + // however prevents deadlock + if (this.gmtCalendar == null) { + this.gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + } + + return this.gmtCalendar; + } + + protected ExceptionInterceptor getExceptionInterceptor() { + return this.exceptionInterceptor; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetInternalMethods.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetInternalMethods.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetInternalMethods.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,184 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + +/** + * This interface is intended to be used by implementors of statement + * interceptors so that implementors can create static or dynamic (via + * java.lang.reflect.Proxy) proxy instances of ResultSets. It consists + * of methods outside of java.sql.Result that are used internally by + * other classes in the driver. + * + * This interface, although public is not designed to + * be consumed publicly other than for the statement interceptor use case. + * + * @version $Id$ + */ +public interface ResultSetInternalMethods extends java.sql.ResultSet { + + /** + * Returns a new instance of this result set, that shares the + * underlying row data. + */ + public abstract ResultSetInternalMethods copy() throws SQLException; + + /** + * Does the result set contain rows, or is it the result of a DDL or DML + * statement? + */ + public abstract boolean reallyResult(); + + /** + * Functions like ResultSet.getObject(), but using the given SQL type + * (as registered during CallableStatement.registerOutParameter()). + */ + public abstract Object getObjectStoredProc(int columnIndex, int desiredSqlType) + throws SQLException; + + /** + * Functions like ResultSet.getObject(), but using the given SQL type + * (as registered during CallableStatement.registerOutParameter()). + */ + public abstract Object getObjectStoredProc(int i, java.util.Map map, + int desiredSqlType) throws SQLException; + + /** + * Functions like ResultSet.getObject(), but using the given SQL type + * (as registered during CallableStatement.registerOutParameter()). + */ + public abstract Object getObjectStoredProc(String columnName, int desiredSqlType) + throws SQLException; + + /** + * Functions like ResultSet.getObject(), but using the given SQL type + * (as registered during CallableStatement.registerOutParameter()). + */ + public abstract Object getObjectStoredProc(String colName, java.util.Map map, + int desiredSqlType) throws SQLException; + + /** + * Returns the server informational message returned from a DDL or DML + * statement (if any), or null if none. + */ + public String getServerInfo(); + + /** + * Returns the update count for this result set (if one exists), otherwise + * -1. + * + * @ return the update count for this result set (if one exists), otherwise + * -1. + */ + public long getUpdateCount(); + + /** + * Returns the AUTO_INCREMENT value for the DDL/DML statement which created + * this result set. + * + * @return the AUTO_INCREMENT value for the DDL/DML statement which created + * this result set. + */ + public long getUpdateID(); + + /** + * Closes this ResultSet and releases resources. + * + * @param calledExplicitly + * was realClose called by the standard ResultSet.close() method, or was it closed internally by the + * driver? + */ + public void realClose(boolean calledExplicitly) throws SQLException; + + /** + * Returns true if this ResultSet is closed + */ + public boolean isClosed() throws SQLException; + + /** + * Sets the first character of the query that was issued to create + * this result set. The character should be upper-cased. + */ + public void setFirstCharOfQuery(char firstCharUpperCase); + + /** + * Sets the statement that "owns" this result set (usually used when the + * result set should internally "belong" to one statement, but is created + * by another. + */ + public void setOwningStatement(com.mysql.jdbc.StatementImpl owningStatement); + + /** + * Returns the first character of the query that was issued to create this + * result set, upper-cased. + */ + public char getFirstCharOfQuery(); + + /** + * Clears the reference to the next result set in a multi-result set + * "chain". + */ + public void clearNextResult(); + + /** + * Returns the next ResultSet in a multi-resultset "chain", if any, + * null if none exists. + */ + public ResultSetInternalMethods getNextResultSet(); + + public void setStatementUsedForFetchingRows(PreparedStatement stmt); + + /** + * @param wrapperStatement + * The wrapperStatement to set. + */ + public void setWrapperStatement(java.sql.Statement wrapperStatement); + + /** + * Builds a hash between column names and their indices for fast retrieval. + * This is done lazily to support findColumn() and get*(String), as it + * can be more expensive than just retrieving result set values by ordinal + * index. + */ + public void buildIndexMapping() throws SQLException; + + public void initializeWithMetadata() throws SQLException; + + /** + * Used by DatabaseMetadata implementations to coerce the metadata returned + * by metadata queries into that required by the JDBC specification. + * + * @param metadataFields the coerced metadata to be applied to result sets + * returned by "SHOW ..." or SELECTs on INFORMATION_SCHEMA performed on behalf + * of methods in DatabaseMetadata. + */ + public void redefineFieldsForDBMD(Field[] metadataFields); + + public void populateCachedMetaData(CachedResultSetMetaData cachedMetaData) throws SQLException; + + public void initializeFromCachedMetaData(CachedResultSetMetaData cachedMetaData); + + public int getBytesSize() throws SQLException; +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetMetaData.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetMetaData.java (.../ResultSetMetaData.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetMetaData.java (.../ResultSetMetaData.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,32 +1,28 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; import java.sql.SQLException; import java.sql.Types; @@ -79,16 +75,21 @@ Field[] fields; boolean useOldAliasBehavior = false; + boolean treatYearAsDate = true; + + private ExceptionInterceptor exceptionInterceptor; /** - * Initialise for a result with a tuple set and a field descriptor set + * Initialize for a result with a tuple set and a field descriptor set * * @param fields * the array of field descriptors */ - public ResultSetMetaData(Field[] fields, boolean useOldAliasBehavior) { + public ResultSetMetaData(Field[] fields, boolean useOldAliasBehavior, boolean treatYearAsDate, ExceptionInterceptor exceptionInterceptor) { this.fields = fields; this.useOldAliasBehavior = useOldAliasBehavior; + this.treatYearAsDate = treatYearAsDate; + this.exceptionInterceptor = exceptionInterceptor; } /** @@ -129,8 +130,13 @@ String javaName = null; if (mysqlName != null) { - javaName = CharsetMapping.getJavaEncodingForMysqlEncoding( - mysqlName, null); + try { + javaName = CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlName); + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; + } } return javaName; @@ -180,7 +186,7 @@ f.isUnsigned(), f.getMysqlType(), f.isBinary() || f.isBlob(), - f.isOpaqueBinary()); + f.isOpaqueBinary(), treatYearAsDate); } /** @@ -247,8 +253,8 @@ public String getColumnName(int column) throws SQLException { if (this.useOldAliasBehavior) { return getField(column).getName(); - } - + } + String name = getField(column).getNameNoAliases(); if (name != null && name.length() == 0) { @@ -376,7 +382,10 @@ case MysqlDefs.FIELD_TYPE_SET: return "SET"; //$NON-NLS-1$ - + + case MysqlDefs.FIELD_TYPE_GEOMETRY: + return "GEOMETRY"; //$NON-NLS-1$ + default: return "UNKNOWN"; //$NON-NLS-1$ } @@ -396,7 +405,7 @@ protected Field getField(int columnIndex) throws SQLException { if ((columnIndex < 1) || (columnIndex > this.fields.length)) { throw SQLError.createSQLException(Messages.getString("ResultSetMetaData.46"), //$NON-NLS-1$ - SQLError.SQL_STATE_INVALID_COLUMN_NUMBER); + SQLError.SQL_STATE_INVALID_COLUMN_NUMBER, this.exceptionInterceptor); } return this.fields[columnIndex - 1]; @@ -718,65 +727,63 @@ return toStringBuf.toString(); } - - static String getClassNameForJavaType(int javaType, - boolean isUnsigned, int mysqlTypeIfKnown, - boolean isBinaryOrBlob, - boolean isOpaqueBinary) { + + static String getClassNameForJavaType(int javaType, boolean isUnsigned, int mysqlTypeIfKnown, + boolean isBinaryOrBlob, boolean isOpaqueBinary, boolean treatYearAsDate) { switch (javaType) { case Types.BIT: case Types.BOOLEAN: - return "java.lang.Boolean"; //$NON-NLS-1$ + return "java.lang.Boolean"; case Types.TINYINT: if (isUnsigned) { - return "java.lang.Integer"; //$NON-NLS-1$ + return "java.lang.Integer"; } - return "java.lang.Integer"; //$NON-NLS-1$ + return "java.lang.Integer"; case Types.SMALLINT: if (isUnsigned) { - return "java.lang.Integer"; //$NON-NLS-1$ + return "java.lang.Integer"; } - return "java.lang.Integer"; //$NON-NLS-1$ + return "java.lang.Integer"; case Types.INTEGER: if (!isUnsigned || mysqlTypeIfKnown == MysqlDefs.FIELD_TYPE_INT24) { - return "java.lang.Integer"; //$NON-NLS-1$ + return "java.lang.Integer"; } - return "java.lang.Long"; //$NON-NLS-1$ + return "java.lang.Long"; case Types.BIGINT: if (!isUnsigned) { - return "java.lang.Long"; //$NON-NLS-1$ + return "java.lang.Long"; } - return "java.math.BigInteger"; //$NON-NLS-1$ + return "java.math.BigInteger"; case Types.DECIMAL: case Types.NUMERIC: - return "java.math.BigDecimal"; //$NON-NLS-1$ + return "java.math.BigDecimal"; case Types.REAL: - return "java.lang.Float"; //$NON-NLS-1$ + return "java.lang.Float"; case Types.FLOAT: case Types.DOUBLE: - return "java.lang.Double"; //$NON-NLS-1$ + return "java.lang.Double"; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: if (!isOpaqueBinary) { - return "java.lang.String"; //$NON-NLS-1$ + return "java.lang.String"; } return "[B"; @@ -794,16 +801,63 @@ } case Types.DATE: - return "java.sql.Date"; //$NON-NLS-1$ + return (treatYearAsDate || mysqlTypeIfKnown != MysqlDefs.FIELD_TYPE_YEAR) ? "java.sql.Date" + : "java.lang.Short"; case Types.TIME: - return "java.sql.Time"; //$NON-NLS-1$ + return "java.sql.Time"; case Types.TIMESTAMP: - return "java.sql.Timestamp"; //$NON-NLS-1$ + return "java.sql.Timestamp"; default: - return "java.lang.Object"; //$NON-NLS-1$ + return "java.lang.Object"; } } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public Object unwrap(Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return Util.cast(iface, this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetRow.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetRow.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ResultSetRow.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,1484 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.Date; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; +import java.util.StringTokenizer; +import java.util.TimeZone; + +/** + * Classes that implement this interface represent one row of data from the + * MySQL server that might be stored in different ways depending on whether the + * result set was streaming (so they wrap a reusable packet), or whether the + * result set was cached or via a server-side cursor (so they represent a + * byte[][]). + * + * Notice that no bounds checking is expected for implementors + * of this interface, it happens in ResultSetImpl. + * + * @version $Id$ + */ +public abstract class ResultSetRow { + protected ExceptionInterceptor exceptionInterceptor; + + protected ResultSetRow(ExceptionInterceptor exceptionInterceptor) { + this.exceptionInterceptor = exceptionInterceptor; + } + + /** + * The metadata of the fields of this result set. + */ + protected Field[] metadata; + + /** + * Called during navigation to next row to close all open + * streams. + */ + public abstract void closeOpenStreams(); + + /** + * Returns data at the given index as an InputStream with no + * character conversion. + * + * @param columnIndex + * of the column value (starting at 0) to return. + * @return the value at the given index as an InputStream or null + * if null. + * + * @throws SQLException if an error occurs while retrieving the value. + */ + public abstract InputStream getBinaryInputStream(int columnIndex) + throws SQLException; + + /** + * Returns the value at the given column (index starts at 0) "raw" (i.e. + * as-returned by the server). + * + * @param index + * of the column value (starting at 0) to return. + * @return the value for the given column (including NULL if it is) + * @throws SQLException + * if an error occurs while retrieving the value. + */ + public abstract byte[] getColumnValue(int index) throws SQLException; + + protected final java.sql.Date getDateFast(int columnIndex, + byte[] dateAsBytes, int offset, int length, MySQLConnection conn, + ResultSetImpl rs, Calendar targetCalendar) throws SQLException { + + int year = 0; + int month = 0; + int day = 0; + + try { + if (dateAsBytes == null) { + return null; + } + + boolean allZeroDate = true; + + boolean onlyTimePresent = false; + + for (int i = 0; i < length; i++) { + if (dateAsBytes[offset + i] == ':') { + onlyTimePresent = true; + break; + } + } + + for (int i = 0; i < length; i++) { + byte b = dateAsBytes[offset + i]; + + if (b == ' ' || b == '-' || b == '/') { + onlyTimePresent = false; + } + + if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/' + && b != '.') { + allZeroDate = false; + + break; + } + } + + if (!onlyTimePresent && allZeroDate) { + + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw SQLError.createSQLException("Value '" + + StringUtils.toString(dateAsBytes) + + "' can not be represented as java.sql.Date", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + // We're left with the case of 'round' to a date Java _can_ + // represent, which is '0001-01-01'. + return rs.fastDateCreate(targetCalendar, 1, 1, 1); + + } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) { + // Convert from TIMESTAMP + switch (length) { + case 29: + case 21: + case 19: { // java.sql.Timestamp format + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 4); + month = StringUtils.getInt(dateAsBytes, offset + 5, + offset + 7); + day = StringUtils.getInt(dateAsBytes, offset + 8, + offset + 10); + + return rs.fastDateCreate(targetCalendar, year, month, day); + } + + case 14: + case 8: { + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 4); + month = StringUtils.getInt(dateAsBytes, offset + 4, + offset + 6); + day = StringUtils.getInt(dateAsBytes, offset + 6, + offset + 8); + + return rs.fastDateCreate(targetCalendar, year, month, day); + } + + case 12: + case 10: + case 6: { + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 2); + + if (year <= 69) { + year = year + 100; + } + + month = StringUtils.getInt(dateAsBytes, offset + 2, + offset + 4); + day = StringUtils.getInt(dateAsBytes, offset + 4, + offset + 6); + + return rs.fastDateCreate(targetCalendar, year + 1900, month, day); + } + + case 4: { + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 4); + + if (year <= 69) { + year = year + 100; + } + + month = StringUtils.getInt(dateAsBytes, offset + 2, + offset + 4); + + return rs.fastDateCreate(targetCalendar, year + 1900, month, 1); + } + + case 2: { + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 2); + + if (year <= 69) { + year = year + 100; + } + + return rs.fastDateCreate(targetCalendar, year + 1900, 1, 1); + } + + default: + throw SQLError + .createSQLException( + Messages + .getString( + "ResultSet.Bad_format_for_Date", + new Object[] { + StringUtils.toString( + dateAsBytes), + Integer.valueOf(columnIndex + 1) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$ + } /* endswitch */ + } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { + + if (length == 2 || length == 1) { + year = StringUtils.getInt(dateAsBytes, offset, offset + + length); + + if (year <= 69) { + year = year + 100; + } + + year += 1900; + } else { + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 4); + } + + return rs.fastDateCreate(targetCalendar, year, 1, 1); + } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) { + return rs.fastDateCreate(targetCalendar, 1970, 1, 1); // Return EPOCH + } else { + if (length < 10) { + if (length == 8) { + return rs.fastDateCreate(targetCalendar, 1970, 1, 1); // Return + // EPOCH for + // TIME + } + + throw SQLError + .createSQLException( + Messages + .getString( + "ResultSet.Bad_format_for_Date", + new Object[] { + StringUtils.toString( + dateAsBytes), + Integer.valueOf(columnIndex + 1) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$ + } + + if (length != 18) { + year = StringUtils.getInt(dateAsBytes, offset + 0, + offset + 4); + month = StringUtils.getInt(dateAsBytes, offset + 5, + offset + 7); + day = StringUtils.getInt(dateAsBytes, offset + 8, + offset + 10); + } else { + // JDK-1.3 timestamp format, not real easy to parse + // positionally :p + StringTokenizer st = new StringTokenizer(StringUtils.toString( + dateAsBytes, offset, length, "ISO8859_1"), "- "); + + year = Integer.parseInt(st.nextToken()); + month = Integer.parseInt(st.nextToken()); + day = Integer.parseInt(st.nextToken()); + } + } + + return rs.fastDateCreate(targetCalendar, year, month, day); + } catch (SQLException sqlEx) { + throw sqlEx; // don't re-wrap + } catch (Exception e) { + SQLException sqlEx = SQLError.createSQLException(Messages.getString( + "ResultSet.Bad_format_for_Date", new Object[] { + StringUtils.toString(dateAsBytes), + Integer.valueOf(columnIndex + 1) }), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); //$NON-NLS-1$ + sqlEx.initCause(e); + + throw sqlEx; + } + } + + public abstract java.sql.Date getDateFast(int columnIndex, + MySQLConnection conn, ResultSetImpl rs, Calendar targetCalendar) throws SQLException; + + /** + * Returns the value at the given column (index starts at 0) as an int. * + * + * @param index + * of the column value (starting at 0) to return. + * @return the value for the given column (returns 0 if NULL, use isNull() + * to determine if the value was actually NULL) + * @throws SQLException + * if an error occurs while retrieving the value. + */ + public abstract int getInt(int columnIndex) throws SQLException; + + /** + * Returns the value at the given column (index starts at 0) as a long. * + * + * @param index + * of the column value (starting at 0) to return. + * @return the value for the given column (returns 0 if NULL, use isNull() + * to determine if the value was actually NULL) + * @throws SQLException + * if an error occurs while retrieving the value. + */ + public abstract long getLong(int columnIndex) throws SQLException; + + /** + * + * @param columnIndex + * @param bits + * @param offset + * @param length + * @param conn + * @param rs + * @param cal + * @return + * @throws SQLException + */ + protected java.sql.Date getNativeDate(int columnIndex, byte[] bits, + int offset, int length, MySQLConnection conn, ResultSetImpl rs, Calendar cal) + throws SQLException { + + int year = 0; + int month = 0; + int day = 0; + + if (length != 0) { + year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8); + + month = bits[offset + 2]; + day = bits[offset + 3]; + } + + if (length == 0 || ((year == 0) && (month == 0) && (day == 0))) { + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw SQLError + .createSQLException( + "Value '0000-00-00' can not be represented as java.sql.Date", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + year = 1; + month = 1; + day = 1; + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastDateCreate(year, month, day, cal); + } + + return rs.fastDateCreate(cal == null ? rs.getCalendarInstanceForSessionOrNew() : cal, year, + month, day); + } + + public abstract Date getNativeDate(int columnIndex, MySQLConnection conn, + ResultSetImpl rs, Calendar cal) throws SQLException; + + protected Object getNativeDateTimeValue(int columnIndex, byte[] bits, + int offset, int length, Calendar targetCalendar, int jdbcType, + int mysqlType, TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException { + + int year = 0; + int month = 0; + int day = 0; + + int hour = 0; + int minute = 0; + int seconds = 0; + + int nanos = 0; + + if (bits == null) { + + return null; + } + + Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn + .getUtcCalendar() + : rs.getCalendarInstanceForSessionOrNew(); + + boolean populatedFromDateTimeValue = false; + + switch (mysqlType) { + case MysqlDefs.FIELD_TYPE_DATETIME: + case MysqlDefs.FIELD_TYPE_TIMESTAMP: + populatedFromDateTimeValue = true; + + if (length != 0) { + year = (bits[offset + 0] & 0xff) + | ((bits[offset + 1] & 0xff) << 8); + month = bits[offset + 2]; + day = bits[offset + 3]; + + if (length > 4) { + hour = bits[offset + 4]; + minute = bits[offset + 5]; + seconds = bits[offset + 6]; + } + + if (length > 7) { + // MySQL uses microseconds + nanos = ((bits[offset + 7] & 0xff) + | ((bits[offset + 8] & 0xff) << 8) + | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000; + } + } + + break; + case MysqlDefs.FIELD_TYPE_DATE: + populatedFromDateTimeValue = true; + + if (bits.length != 0) { + year = (bits[offset + 0] & 0xff) + | ((bits[offset + 1] & 0xff) << 8); + month = bits[offset + 2]; + day = bits[offset + 3]; + } + + break; + case MysqlDefs.FIELD_TYPE_TIME: + populatedFromDateTimeValue = true; + + if (bits.length != 0) { + // bits[0] // skip tm->neg + // binaryData.readLong(); // skip daysPart + hour = bits[offset + 5]; + minute = bits[offset + 6]; + seconds = bits[offset + 7]; + } + + year = 1970; + month = 1; + day = 1; + + break; + default: + populatedFromDateTimeValue = false; + } + + switch (jdbcType) { + case Types.TIME: + if (populatedFromDateTimeValue) { + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimeCreate(hour, minute, seconds, targetCalendar, this.exceptionInterceptor); + } + + Time time = TimeUtil.fastTimeCreate(rs + .getCalendarInstanceForSessionOrNew(), hour, minute, + seconds, this.exceptionInterceptor); + + Time adjustedTime = TimeUtil.changeTimezone(conn, + sessionCalendar, targetCalendar, time, conn + .getServerTimezoneTZ(), tz, rollForward); + + return adjustedTime; + } + + return rs.getNativeTimeViaParseConversion(columnIndex + 1, + targetCalendar, tz, rollForward); + + case Types.DATE: + if (populatedFromDateTimeValue) { + if ((year == 0) && (month == 0) && (day == 0)) { + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw new SQLException( + "Value '0000-00-00' can not be represented as java.sql.Date", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + } + + year = 1; + month = 1; + day = 1; + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastDateCreate(year, month, day, targetCalendar); + } + + return rs + .fastDateCreate( + rs.getCalendarInstanceForSessionOrNew(), year, + month, day); + } + + return rs.getNativeDateViaParseConversion(columnIndex + 1); + case Types.TIMESTAMP: + if (populatedFromDateTimeValue) { + if ((year == 0) && (month == 0) && (day == 0)) { + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw new SQLException( + "Value '0000-00-00' can not be represented as java.sql.Timestamp", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + } + + year = 1; + month = 1; + day = 1; + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, year, month, day, hour, minute, + seconds, nanos); + } + + Timestamp ts = rs.fastTimestampCreate(rs + .getCalendarInstanceForSessionOrNew(), year, month, + day, hour, minute, seconds, nanos); + + Timestamp adjustedTs = TimeUtil.changeTimezone(conn, + sessionCalendar, targetCalendar, ts, conn + .getServerTimezoneTZ(), tz, rollForward); + + return adjustedTs; + } + + return rs.getNativeTimestampViaParseConversion(columnIndex + 1, + targetCalendar, tz, rollForward); + + default: + throw new SQLException( + "Internal error - conversion method doesn't support this type", + SQLError.SQL_STATE_GENERAL_ERROR); + } + } + + public abstract Object getNativeDateTimeValue(int columnIndex, + Calendar targetCalendar, int jdbcType, int mysqlType, + TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs) + throws SQLException; + + protected double getNativeDouble(byte[] bits, int offset) { + long valueAsLong = (bits[offset + 0] & 0xff) + | ((long) (bits[offset + 1] & 0xff) << 8) + | ((long) (bits[offset + 2] & 0xff) << 16) + | ((long) (bits[offset + 3] & 0xff) << 24) + | ((long) (bits[offset + 4] & 0xff) << 32) + | ((long) (bits[offset + 5] & 0xff) << 40) + | ((long) (bits[offset + 6] & 0xff) << 48) + | ((long) (bits[offset + 7] & 0xff) << 56); + + return Double.longBitsToDouble(valueAsLong); + } + + public abstract double getNativeDouble(int columnIndex) throws SQLException; + + protected float getNativeFloat(byte[] bits, int offset) { + int asInt = (bits[offset + 0] & 0xff) + | ((bits[offset + 1] & 0xff) << 8) + | ((bits[offset + 2] & 0xff) << 16) + | ((bits[offset + 3] & 0xff) << 24); + + return Float.intBitsToFloat(asInt); + } + + public abstract float getNativeFloat(int columnIndex) throws SQLException; + + protected int getNativeInt(byte[] bits, int offset) { + + int valueAsInt = (bits[offset + 0] & 0xff) + | ((bits[offset + 1] & 0xff) << 8) + | ((bits[offset + 2] & 0xff) << 16) + | ((bits[offset + 3] & 0xff) << 24); + + return valueAsInt; + } + + public abstract int getNativeInt(int columnIndex) throws SQLException; + + protected long getNativeLong(byte[] bits, int offset) { + long valueAsLong = (bits[offset + 0] & 0xff) + | ((long) (bits[offset + 1] & 0xff) << 8) + | ((long) (bits[offset + 2] & 0xff) << 16) + | ((long) (bits[offset + 3] & 0xff) << 24) + | ((long) (bits[offset + 4] & 0xff) << 32) + | ((long) (bits[offset + 5] & 0xff) << 40) + | ((long) (bits[offset + 6] & 0xff) << 48) + | ((long) (bits[offset + 7] & 0xff) << 56); + + return valueAsLong; + } + + public abstract long getNativeLong(int columnIndex) throws SQLException; + + protected short getNativeShort(byte[] bits, int offset) { + short asShort = (short) ((bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8)); + + return asShort; + } + + public abstract short getNativeShort(int columnIndex) throws SQLException; + + /** + * + * @param columnIndex + * @param bits + * @param offset + * @param length + * @param targetCalendar + * @param tz + * @param rollForward + * @param conn + * @param rs + * @return + * @throws SQLException + */ + protected Time getNativeTime(int columnIndex, byte[] bits, int offset, + int length, Calendar targetCalendar, TimeZone tz, + boolean rollForward, MySQLConnection conn, ResultSetImpl rs) + throws SQLException { + + int hour = 0; + int minute = 0; + int seconds = 0; + + if (length != 0) { + // bits[0] // skip tm->neg + // binaryData.readLong(); // skip daysPart + hour = bits[offset + 5]; + minute = bits[offset + 6]; + seconds = bits[offset + 7]; + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimeCreate(hour, minute, seconds, targetCalendar, this.exceptionInterceptor); + } + + Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + Time time = TimeUtil.fastTimeCreate(sessionCalendar, hour, minute, + seconds, this.exceptionInterceptor); + + Time adjustedTime = TimeUtil.changeTimezone(conn, sessionCalendar, + targetCalendar, time, conn.getServerTimezoneTZ(), tz, + rollForward); + + return adjustedTime; + } + } + + public abstract Time getNativeTime(int columnIndex, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException; + + protected Timestamp getNativeTimestamp(byte[] bits, int offset, int length, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException { + int year = 0; + int month = 0; + int day = 0; + + int hour = 0; + int minute = 0; + int seconds = 0; + + int nanos = 0; + + if (length != 0) { + year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8); + month = bits[offset + 2]; + day = bits[offset + 3]; + + if (length > 4) { + hour = bits[offset + 4]; + minute = bits[offset + 5]; + seconds = bits[offset + 6]; + } + + if (length > 7) { + // MySQL uses microseconds + nanos = ((bits[offset + 7] & 0xff) + | ((bits[offset + 8] & 0xff) << 8) + | ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000; + } + } + + if (length == 0 || ((year == 0) && (month == 0) && (day == 0))) { + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw SQLError + .createSQLException( + "Value '0000-00-00' can not be represented as java.sql.Timestamp", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + year = 1; + month = 1; + day = 1; + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, year, month, + day, hour, minute, seconds, nanos); + } + + Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn + .getUtcCalendar() + : rs.getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + Timestamp ts = rs.fastTimestampCreate(sessionCalendar, year, month, + day, hour, minute, seconds, nanos); + + Timestamp adjustedTs = TimeUtil.changeTimezone(conn, + sessionCalendar, targetCalendar, ts, conn + .getServerTimezoneTZ(), tz, rollForward); + + return adjustedTs; + } + } + + public abstract Timestamp getNativeTimestamp(int columnIndex, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException; + + public abstract Reader getReader(int columnIndex) throws SQLException; + + /** + * Returns the value at the given column (index starts at 0) as a + * java.lang.String with the requested encoding, using the given + * MySQLConnection to find character converters. + * + * @param index + * of the column value (starting at 0) to return. + * @param encoding + * the Java name for the character encoding + * @param conn + * the connection that created this result set row + * + * @return the value for the given column (including NULL if it is) as a + * String + * + * @throws SQLException + * if an error occurs while retrieving the value. + */ + public abstract String getString(int index, String encoding, + MySQLConnection conn) throws SQLException; + + /** + * Convenience method for turning a byte[] into a string with the given + * encoding. + * + * @param encoding + * the Java encoding name for the byte[] -> char conversion + * @param conn + * the MySQLConnection that created the result set + * @param value + * the String value as a series of bytes, encoded using + * "encoding" + * @param offset + * where to start the decoding + * @param length + * how many bytes to decode + * + * @return the String as decoded from bytes with the given encoding + * + * @throws SQLException + * if an error occurs + */ + protected String getString(String encoding, MySQLConnection conn, + byte[] value, int offset, int length) throws SQLException { + String stringVal = null; + + if ((conn != null) && conn.getUseUnicode()) { + try { + if (encoding == null) { + stringVal = StringUtils.toString(value); + } else { + SingleByteCharsetConverter converter = conn + .getCharsetConverter(encoding); + + if (converter != null) { + stringVal = converter.toString(value, offset, length); + } else { + stringVal = StringUtils.toString(value, offset, length, encoding); + } + } + } catch (java.io.UnsupportedEncodingException E) { + throw SQLError + .createSQLException( + Messages + .getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$ + + encoding + "'.", "0S100", this.exceptionInterceptor); + } + } else { + stringVal = StringUtils.toAsciiString(value, offset, length); + } + + return stringVal; + } + + protected Time getTimeFast(int columnIndex, byte[] timeAsBytes, int offset, + int fullLength, Calendar targetCalendar, TimeZone tz, + boolean rollForward, MySQLConnection conn, ResultSetImpl rs) + throws SQLException { + + int hr = 0; + int min = 0; + int sec = 0; + int nanos = 0; + + int decimalIndex = -1; + + try { + + if (timeAsBytes == null) { + return null; + } + + boolean allZeroTime = true; + boolean onlyTimePresent = false; + + for (int i = 0; i < fullLength; i++) { + if (timeAsBytes[offset + i] == ':') { + onlyTimePresent = true; + break; + } + } + + for (int i = 0; i < fullLength; i++) { + if (timeAsBytes[offset + i] == '.') { + decimalIndex = i; + break; + } + } + + for (int i = 0; i < fullLength; i++) { + byte b = timeAsBytes[offset + i]; + + if (b == ' ' || b == '-' || b == '/') { + onlyTimePresent = false; + } + + if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/' + && b != '.') { + allZeroTime = false; + + break; + } + } + + if (!onlyTimePresent && allZeroTime) { + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw SQLError.createSQLException("Value '" + + StringUtils.toString(timeAsBytes) + + "' can not be represented as java.sql.Time", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + // We're left with the case of 'round' to a time Java _can_ + // represent, which is '00:00:00' + return rs.fastTimeCreate(targetCalendar, 0, 0, 0); + } + + Field timeColField = this.metadata[columnIndex]; + + int length = fullLength; + + if (decimalIndex != -1) { + + length = decimalIndex; + + if ((decimalIndex + 2) <= fullLength) { + nanos = StringUtils.getInt(timeAsBytes, offset + decimalIndex + 1, offset + fullLength); + + int numDigits = (fullLength) - (decimalIndex + 1); + + if (numDigits < 9) { + int factor = (int)(Math.pow(10, 9 - numDigits)); + nanos = nanos * factor; + } + } else { + throw new IllegalArgumentException(); // re-thrown + // further + // down + // with + // a + // much better error message + } + } + + if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) { + + switch (length) { + case 19: { // YYYY-MM-DD hh:mm:ss + + hr = StringUtils.getInt(timeAsBytes, offset + length - 8, + offset + length - 6); + min = StringUtils.getInt(timeAsBytes, offset + length - 5, + offset + length - 3); + sec = StringUtils.getInt(timeAsBytes, offset + length - 2, + offset + length); + } + + break; + case 14: + case 12: { + hr = StringUtils.getInt(timeAsBytes, offset + length - 6, + offset + length - 4); + min = StringUtils.getInt(timeAsBytes, offset + length - 4, + offset + length - 2); + sec = StringUtils.getInt(timeAsBytes, offset + length - 2, + offset + length); + } + + break; + + case 10: { + hr = StringUtils + .getInt(timeAsBytes, offset + 6, offset + 8); + min = StringUtils.getInt(timeAsBytes, offset + 8, + offset + 10); + sec = 0; + } + + break; + + default: + throw SQLError + .createSQLException( + Messages + .getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$ + + (columnIndex + 1) + + "(" + + timeColField + ").", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } /* endswitch */ + + @SuppressWarnings("unused") + SQLWarning precisionLost = new SQLWarning( + Messages + .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$ + + columnIndex + "(" + timeColField + ")."); + /* + * if (this.warningChain == null) { this.warningChain = + * precisionLost; } else { + * this.warningChain.setNextWarning(precisionLost); } + */ + } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) { + hr = StringUtils.getInt(timeAsBytes, offset + 11, offset + 13); + min = StringUtils.getInt(timeAsBytes, offset + 14, offset + 16); + sec = StringUtils.getInt(timeAsBytes, offset + 17, offset + 19); + + @SuppressWarnings("unused") + SQLWarning precisionLost = new SQLWarning( + Messages + .getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$ + + (columnIndex + 1) + "(" + timeColField + ")."); + + /* + * if (this.warningChain == null) { this.warningChain = + * precisionLost; } else { + * this.warningChain.setNextWarning(precisionLost); } + */ + } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) { + return rs.fastTimeCreate(null, 0, 0, 0); // midnight on the + // given + // date + } else { + // convert a String to a Time + if ((length != 5) && (length != 8)) { + throw SQLError.createSQLException(Messages + .getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$ + + StringUtils.toString(timeAsBytes) + + Messages.getString("ResultSet.___in_column__268") + + (columnIndex + 1), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + hr = StringUtils.getInt(timeAsBytes, offset + 0, offset + 2); + min = StringUtils.getInt(timeAsBytes, offset + 3, offset + 5); + sec = (length == 5) ? 0 : StringUtils.getInt(timeAsBytes, + offset + 6, offset + 8); + } + + Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew(); + + if (!rs.useLegacyDatetimeCode) { + // TODO: return rs.fastTimeCreate(targetCalendar, hr, min, sec, nanos); + // java.sql.Time doesn't contain fractional part, so PreparedStatement.setTime/getTime can't deal with TIME(n) fractional part. + // There may be better mappings to high-precision time coming in JDBC-5 with the adoption of JSR-310. + return rs.fastTimeCreate(targetCalendar, hr, min, sec); + } + + synchronized (sessionCalendar) { + return TimeUtil.changeTimezone(conn, sessionCalendar, + targetCalendar, rs.fastTimeCreate(sessionCalendar, hr, + min, sec), conn.getServerTimezoneTZ(), tz, + rollForward); + // TODO: min, sec, nanos), conn.getServerTimezoneTZ(), tz, + // java.sql.Time doesn't contain fractional part, so PreparedStatement.setTime/getTime can't deal with TIME(n) fractional part. + // There may be better mappings to high-precision time coming in JDBC-5 with the adoption of JSR-310. + } + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(ex); + + throw sqlEx; + } + } + + public abstract Time getTimeFast(int columnIndex, Calendar targetCalendar, + TimeZone tz, boolean rollForward, MySQLConnection conn, + ResultSetImpl rs) throws SQLException; + + protected Timestamp getTimestampFast(int columnIndex, + byte[] timestampAsBytes, int offset, int length, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException { + + try { + Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn + .getUtcCalendar() + : rs.getCalendarInstanceForSessionOrNew(); + + synchronized (sessionCalendar) { + boolean allZeroTimestamp = true; + + boolean onlyTimePresent = false; + + for (int i = 0; i < length; i++) { + if (timestampAsBytes[offset + i] == ':') { + onlyTimePresent = true; + break; + } + } + + for (int i = 0; i < length; i++) { + byte b = timestampAsBytes[offset + i]; + + if (b == ' ' || b == '-' || b == '/') { + onlyTimePresent = false; + } + + if (b != '0' && b != ' ' && b != ':' && b != '-' + && b != '/' && b != '.') { + allZeroTimestamp = false; + + break; + } + } + + if (!onlyTimePresent && allZeroTimestamp) { + + if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL + .equals(conn.getZeroDateTimeBehavior())) { + + return null; + } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION + .equals(conn.getZeroDateTimeBehavior())) { + throw SQLError + .createSQLException( + "Value '" + + StringUtils.toString(timestampAsBytes) + + "' can not be represented as java.sql.Timestamp", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, 1, 1, 1, 0, 0, 0, 0); + } + // We're left with the case of 'round' to a date Java _can_ + // represent, which is '0001-01-01'. + return rs.fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0); + + } else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, StringUtils + .getInt(timestampAsBytes, offset, 4), 1, 1, 0, + 0, 0, 0); + } + + return TimeUtil.changeTimezone(conn, sessionCalendar, + targetCalendar, rs.fastTimestampCreate( + sessionCalendar, StringUtils.getInt( + timestampAsBytes, offset, 4), 1, 1, + 0, 0, 0, 0), conn.getServerTimezoneTZ(), + tz, rollForward); + } else { + if (timestampAsBytes[offset + length - 1] == '.') { + length--; + } + + // Convert from TIMESTAMP or DATE + + int year = 0; + int month = 0; + int day = 0; + int hour = 0; + int minutes = 0; + int seconds = 0; + int nanos = 0; + + switch (length) { + case 29: + case 26: + case 25: + case 24: + case 23: + case 22: + case 21: + case 20: + case 19: { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 4); + month = StringUtils.getInt(timestampAsBytes, + offset + 5, offset + 7); + day = StringUtils.getInt(timestampAsBytes, + offset + 8, offset + 10); + hour = StringUtils.getInt(timestampAsBytes, + offset + 11, offset + 13); + minutes = StringUtils.getInt(timestampAsBytes, + offset + 14, offset + 16); + seconds = StringUtils.getInt(timestampAsBytes, + offset + 17, offset + 19); + + nanos = 0; + + if (length > 19) { + int decimalIndex = -1; + + for (int i = 0; i < length; i++) { + if (timestampAsBytes[offset + i] == '.') { + decimalIndex = i; + } + } + + if (decimalIndex != -1) { + if ((decimalIndex + 2) <= length) { + nanos = StringUtils.getInt( + timestampAsBytes, offset + decimalIndex + 1, + offset + length); + + int numDigits = (length) - (decimalIndex + 1); + + if (numDigits < 9) { + int factor = (int)(Math.pow(10, 9 - numDigits)); + nanos = nanos * factor; + } + } else { + throw new IllegalArgumentException(); // re-thrown + // further + // down + // with + // a + // much better error message + } + } + } + + break; + } + + case 14: { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 4); + month = StringUtils.getInt(timestampAsBytes, + offset + 4, offset + 6); + day = StringUtils.getInt(timestampAsBytes, + offset + 6, offset + 8); + hour = StringUtils.getInt(timestampAsBytes, + offset + 8, offset + 10); + minutes = StringUtils.getInt(timestampAsBytes, + offset + 10, offset + 12); + seconds = StringUtils.getInt(timestampAsBytes, + offset + 12, offset + 14); + + break; + } + + case 12: { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 2); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + + month = StringUtils.getInt(timestampAsBytes, + offset + 2, offset + 4); + day = StringUtils.getInt(timestampAsBytes, + offset + 4, offset + 6); + hour = StringUtils.getInt(timestampAsBytes, + offset + 6, offset + 8); + minutes = StringUtils.getInt(timestampAsBytes, + offset + 8, offset + 10); + seconds = StringUtils.getInt(timestampAsBytes, + offset + 10, offset + 12); + + break; + } + + case 10: { + boolean hasDash = false; + + for (int i = 0; i < length; i++) { + if (timestampAsBytes[offset + i] == '-') { + hasDash = true; + break; + } + } + + if ((this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) + || hasDash) { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 4); + month = StringUtils.getInt(timestampAsBytes, + offset + 5, offset + 7); + day = StringUtils.getInt(timestampAsBytes, + offset + 8, offset + 10); + hour = 0; + minutes = 0; + } else { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 2); + + if (year <= 69) { + year = (year + 100); + } + + month = StringUtils.getInt(timestampAsBytes, + offset + 2, offset + 4); + day = StringUtils.getInt(timestampAsBytes, + offset + 4, offset + 6); + hour = StringUtils.getInt(timestampAsBytes, + offset + 6, offset + 8); + minutes = StringUtils.getInt(timestampAsBytes, + offset + 8, offset + 10); + + year += 1900; // two-digit year + } + + break; + } + + case 8: { + boolean hasColon = false; + + for (int i = 0; i < length; i++) { + if (timestampAsBytes[offset + i] == ':') { + hasColon = true; + break; + } + } + + if (hasColon) { + hour = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 2); + minutes = StringUtils.getInt(timestampAsBytes, + offset + 3, offset + 5); + seconds = StringUtils.getInt(timestampAsBytes, + offset + 6, offset + 8); + + year = 1970; + month = 1; + day = 1; + + break; + } + + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 4); + month = StringUtils.getInt(timestampAsBytes, + offset + 4, offset + 6); + day = StringUtils.getInt(timestampAsBytes, + offset + 6, offset + 8); + + year -= 1900; + month--; + + break; + } + + case 6: { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 2); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + + month = StringUtils.getInt(timestampAsBytes, + offset + 2, offset + 4); + day = StringUtils.getInt(timestampAsBytes, + offset + 4, offset + 6); + + break; + } + + case 4: { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 2); + + if (year <= 69) { + year = (year + 100); + } + + month = StringUtils.getInt(timestampAsBytes, + offset + 2, offset + 4); + + day = 1; + + break; + } + + case 2: { + year = StringUtils.getInt(timestampAsBytes, + offset + 0, offset + 2); + + if (year <= 69) { + year = (year + 100); + } + + year += 1900; + month = 1; + day = 1; + + break; + } + + default: + throw new java.sql.SQLException( + "Bad format for Timestamp '" + + StringUtils.toString(timestampAsBytes) + + "' in column " + (columnIndex + 1) + + ".", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + } + + if (!rs.useLegacyDatetimeCode) { + return TimeUtil.fastTimestampCreate(tz, + year, month, + day, hour, minutes, seconds, + nanos); + } + + return TimeUtil + .changeTimezone(conn, sessionCalendar, + targetCalendar, rs.fastTimestampCreate( + sessionCalendar, year, month, + day, hour, minutes, seconds, + nanos), conn + .getServerTimezoneTZ(), tz, + rollForward); + } + } + } catch (RuntimeException e) { + SQLException sqlEx = SQLError.createSQLException("Cannot convert value '" + + getString(columnIndex, "ISO8859_1", conn) + + "' from column " + (columnIndex + 1) + " to TIMESTAMP.", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + sqlEx.initCause(e); + + throw sqlEx; + } + } + + public abstract Timestamp getTimestampFast(int columnIndex, + Calendar targetCalendar, TimeZone tz, boolean rollForward, + MySQLConnection conn, ResultSetImpl rs) throws SQLException; + + /** + * Could the column value at the given index (which starts at 0) be + * interpreted as a floating-point number (has +/-/E/e in it)? + * + * @param index + * of the column value (starting at 0) to check. + * + * @return true if the column value at the given index looks like it might + * be a floating-point number, false if not. + * + * @throws SQLException + * if an error occurs + */ + public abstract boolean isFloatingPointNumber(int index) + throws SQLException; + + /** + * Is the column value at the given index (which starts at 0) NULL? + * + * @param index + * of the column value (starting at 0) to check. + * + * @return true if the column value is NULL, false if not. + * + * @throws SQLException + * if an error occurs + */ + public abstract boolean isNull(int index) throws SQLException; + + /** + * Returns the length of the column at the given index (which starts at 0). + * + * @param index + * of the column value (starting at 0) for which to return the + * length. + * @return the length of the requested column, 0 if null (clients of this + * interface should use isNull() beforehand to determine status of + * NULL values in the column). + * + * @throws SQLException + */ + public abstract long length(int index) throws SQLException; + + /** + * Sets the given column value (only works currently with + * ByteArrayRowHolder). + * + * @param index + * index of the column value (starting at 0) to set. + * @param value + * the (raw) value to set + * + * @throws SQLException + * if an error occurs, or the concrete RowHolder doesn't support + * this operation. + */ + public abstract void setColumnValue(int index, byte[] value) + throws SQLException; + + public ResultSetRow setMetadata(Field[] f) throws SQLException { + this.metadata = f; + + return this; + } + + public abstract int getBytesSize(); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowData.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowData.java (.../RowData.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowData.java (.../RowData.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2006 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; @@ -34,18 +33,13 @@ * @author dgan */ public interface RowData { - // ~ Static fields/initializers - // --------------------------------------------- /** * What's returned for the size of a result set when its size can not be * determined. */ public static final int RESULT_SET_SIZE_UNKNOWN = -1; - // ~ Methods - // ---------------------------------------------------------------- - /** * Adds a row to this row data. * @@ -54,7 +48,7 @@ * @throws SQLException * if a database error occurs */ - void addRow(byte[][] row) throws SQLException; + void addRow(ResultSetRow row) throws SQLException; /** * Moves to after last. @@ -97,7 +91,7 @@ * @throws SQLException * if a database error occurs */ - Object[] getAt(int index) throws SQLException; + ResultSetRow getAt(int index) throws SQLException; /** * Returns the current position in the result set as a row number. @@ -111,7 +105,7 @@ /** * Returns the result set that 'owns' this RowData */ - ResultSet getOwner(); + ResultSetInternalMethods getOwner(); /** * Returns true if another row exsists. @@ -196,7 +190,7 @@ * @throws SQLException * if a database error occurs */ - Object[] next() throws SQLException; + ResultSetRow next() throws SQLException; /** * Removes the row at the given index. @@ -224,7 +218,7 @@ * @param rs * the result set that 'owns' this RowData */ - void setOwner(ResultSet rs); + void setOwner(ResultSetImpl rs); /** * Only works on non dynamic result sets. @@ -239,4 +233,13 @@ * Did this result set have no rows? */ boolean wasEmpty(); + + /** + * Sometimes the driver doesn't have metadata until after + * the statement has the result set in-hand (because it's cached), + * so it can call this to set it after the fact. + * + * @param metadata field-level metadata for the result set + */ + void setMetadata(Field[] metadata); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataCursor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataCursor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataCursor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,482 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * Model for result set data backed by a cursor. Only works for forward-only + * result sets (but still works with updatable concurrency). + * + * @version $Id: CursorRowProvider.java,v 1.1.2.1 2005/05/19 18:31:49 mmatthews + * Exp $ + */ +public class RowDataCursor implements RowData { + + private final static int BEFORE_START_OF_ROWS = -1; + + /** + * The cache of rows we have retrieved from the server. + */ + private List fetchedRows; + + /** + * Where we are positionaly in the entire result set, used mostly to + * facilitate easy 'isBeforeFirst()' and 'isFirst()' methods. + */ + private int currentPositionInEntireResult = BEFORE_START_OF_ROWS; + + /** + * Position in cache of rows, used to determine if we need to fetch more + * rows from the server to satisfy a request for the next row. + */ + private int currentPositionInFetchedRows = BEFORE_START_OF_ROWS; + + /** + * The result set that we 'belong' to. + */ + private ResultSetImpl owner; + + /** + * Have we been told from the server that we have seen the last row? + */ + private boolean lastRowFetched = false; + + /** + * Field-level metadata from the server. We need this, because it is not + * sent for each batch of rows, but we need the metadata to unpack the + * results for each field. + */ + private Field[] metadata; + + /** + * Communications channel to the server + */ + private MysqlIO mysql; + + /** + * Identifier for the statement that created this cursor. + */ + private long statementIdOnServer; + + /** + * The prepared statement that created this cursor. + */ + private ServerPreparedStatement prepStmt; + + /** + * The server status for 'last-row-sent'...This might belong in mysqldefs, + * but it it only ever referenced from here. + */ + private static final int SERVER_STATUS_LAST_ROW_SENT = 128; + + /** + * Have we attempted to fetch any rows yet? + */ + private boolean firstFetchCompleted = false; + + private boolean wasEmpty = false; + + private boolean useBufferRowExplicit = false; + + /** + * Creates a new cursor-backed row provider. + * + * @param ioChannel + * connection to the server. + * @param creatingStatement + * statement that opened the cursor. + * @param metadata + * field-level metadata for the results that this cursor covers. + */ + public RowDataCursor(MysqlIO ioChannel, + ServerPreparedStatement creatingStatement, Field[] metadata) { + this.currentPositionInEntireResult = BEFORE_START_OF_ROWS; + this.metadata = metadata; + this.mysql = ioChannel; + this.statementIdOnServer = creatingStatement.getServerStatementId(); + this.prepStmt = creatingStatement; + this.useBufferRowExplicit = MysqlIO.useBufferRowExplicit(this.metadata); + + } + + /** + * Returns true if we got the last element. + * + * @return DOCUMENT ME! + */ + public boolean isAfterLast() { + return lastRowFetched + && this.currentPositionInFetchedRows > this.fetchedRows.size(); + } + + /** + * Only works on non dynamic result sets. + * + * @param index + * row number to get at + * @return row data at index + * @throws SQLException + * if a database error occurs + */ + public ResultSetRow getAt(int ind) throws SQLException { + notSupported(); + + return null; + } + + /** + * Returns if iteration has not occured yet. + * + * @return true if before first row + * @throws SQLException + * if a database error occurs + */ + public boolean isBeforeFirst() throws SQLException { + return this.currentPositionInEntireResult < 0; + } + + /** + * Moves the current position in the result set to the given row number. + * + * @param rowNumber + * row to move to + * @throws SQLException + * if a database error occurs + */ + public void setCurrentRow(int rowNumber) throws SQLException { + notSupported(); + } + + /** + * Returns the current position in the result set as a row number. + * + * @return the current row number + * @throws SQLException + * if a database error occurs + */ + public int getCurrentRowNumber() throws SQLException { + return this.currentPositionInEntireResult + 1; + } + + /** + * Returns true if the result set is dynamic. + * + * This means that move back and move forward won't work because we do not + * hold on to the records. + * + * @return true if this result set is streaming from the server + */ + public boolean isDynamic() { + return true; + } + + /** + * Has no records. + * + * @return true if no records + * @throws SQLException + * if a database error occurs + */ + public boolean isEmpty() throws SQLException { + return this.isBeforeFirst() && this.isAfterLast(); + } + + /** + * Are we on the first row of the result set? + * + * @return true if on first row + * @throws SQLException + * if a database error occurs + */ + public boolean isFirst() throws SQLException { + return this.currentPositionInEntireResult == 0; + } + + /** + * Are we on the last row of the result set? + * + * @return true if on last row + * @throws SQLException + * if a database error occurs + */ + public boolean isLast() throws SQLException { + return this.lastRowFetched + && this.currentPositionInFetchedRows == (this.fetchedRows + .size() - 1); + } + + /** + * Adds a row to this row data. + * + * @param row + * the row to add + * @throws SQLException + * if a database error occurs + */ + public void addRow(ResultSetRow row) throws SQLException { + notSupported(); + } + + /** + * Moves to after last. + * + * @throws SQLException + * if a database error occurs + */ + public void afterLast() throws SQLException { + notSupported(); + } + + /** + * Moves to before first. + * + * @throws SQLException + * if a database error occurs + */ + public void beforeFirst() throws SQLException { + notSupported(); + } + + /** + * Moves to before last so next el is the last el. + * + * @throws SQLException + * if a database error occurs + */ + public void beforeLast() throws SQLException { + notSupported(); + } + + /** + * We're done. + * + * @throws SQLException + * if a database error occurs + */ + public void close() throws SQLException { + + this.metadata = null; + this.owner = null; + } + + /** + * Returns true if another row exists. + * + * @return true if more rows + * @throws SQLException + * if a database error occurs + */ + public boolean hasNext() throws SQLException { + + if (this.fetchedRows != null && this.fetchedRows.size() == 0) { + return false; + } + + if (this.owner != null && this.owner.owningStatement != null) { + int maxRows = this.owner.owningStatement.maxRows; + + if (maxRows != -1 && this.currentPositionInEntireResult + 1 > maxRows) { + return false; + } + } + + if (this.currentPositionInEntireResult != BEFORE_START_OF_ROWS) { + // Case, we've fetched some rows, but are not at end of fetched + // block + if (this.currentPositionInFetchedRows < (this.fetchedRows.size() - 1)) { + return true; + } else if (this.currentPositionInFetchedRows == this.fetchedRows + .size() + && this.lastRowFetched) { + return false; + } else { + // need to fetch to determine + fetchMoreRows(); + + return (this.fetchedRows.size() > 0); + } + } + + // Okay, no rows _yet_, so fetch 'em + + fetchMoreRows(); + + return this.fetchedRows.size() > 0; + } + + /** + * Moves the current position relative 'rows' from the current position. + * + * @param rows + * the relative number of rows to move + * @throws SQLException + * if a database error occurs + */ + public void moveRowRelative(int rows) throws SQLException { + notSupported(); + } + + /** + * Returns the next row. + * + * @return the next row value + * @throws SQLException + * if a database error occurs + */ + public ResultSetRow next() throws SQLException { + if (this.fetchedRows == null && this.currentPositionInEntireResult != BEFORE_START_OF_ROWS) { + throw SQLError.createSQLException( + Messages + .getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, mysql.getExceptionInterceptor()); + } + + if (!hasNext()) { + return null; + } + + this.currentPositionInEntireResult++; + this.currentPositionInFetchedRows++; + + // Catch the forced scroll-passed-end + if (this.fetchedRows != null && this.fetchedRows.size() == 0) { + return null; + } + + if (this.currentPositionInFetchedRows > (this.fetchedRows.size() - 1)) { + fetchMoreRows(); + this.currentPositionInFetchedRows = 0; + } + + ResultSetRow row = this.fetchedRows + .get(this.currentPositionInFetchedRows); + + row.setMetadata(this.metadata); + + return row; + } + + /** + * + */ + private void fetchMoreRows() throws SQLException { + if (this.lastRowFetched) { + this.fetchedRows = new ArrayList(0); + return; + } + + synchronized (this.owner.connection.getConnectionMutex()) { + boolean oldFirstFetchCompleted = this.firstFetchCompleted; + + if (!this.firstFetchCompleted) { + this.firstFetchCompleted = true; + } + + int numRowsToFetch = this.owner.getFetchSize(); + + if (numRowsToFetch == 0) { + numRowsToFetch = this.prepStmt.getFetchSize(); + } + + if (numRowsToFetch == Integer.MIN_VALUE) { + // Handle the case where the user used 'old' + // streaming result sets + + numRowsToFetch = 1; + } + + this.fetchedRows = this.mysql.fetchRowsViaCursor(this.fetchedRows, + this.statementIdOnServer, this.metadata, numRowsToFetch, + this.useBufferRowExplicit); + this.currentPositionInFetchedRows = BEFORE_START_OF_ROWS; + + if ((this.mysql.getServerStatus() & SERVER_STATUS_LAST_ROW_SENT) != 0) { + this.lastRowFetched = true; + + if (!oldFirstFetchCompleted && this.fetchedRows.size() == 0) { + this.wasEmpty = true; + } + } + } + } + + /** + * Removes the row at the given index. + * + * @param index + * the row to move to + * @throws SQLException + * if a database error occurs + */ + public void removeRow(int ind) throws SQLException { + notSupported(); + } + + /** + * Only works on non dynamic result sets. + * + * @return the size of this row data + */ + public int size() { + return RESULT_SET_SIZE_UNKNOWN; + } + + protected void nextRecord() throws SQLException { + + } + + private void notSupported() throws SQLException { + throw new OperationNotSupportedException(); + } + + /* + * (non-Javadoc) + * + * @see com.mysql.jdbc.RowProvider#setOwner(com.mysql.jdbc.ResultSet) + */ + public void setOwner(ResultSetImpl rs) { + this.owner = rs; + } + + /* + * (non-Javadoc) + * + * @see com.mysql.jdbc.RowProvider#getOwner() + */ + public ResultSetInternalMethods getOwner() { + return this.owner; + } + + public boolean wasEmpty() { + return this.wasEmpty; + } + + public void setMetadata(Field[] metadata) { + this.metadata = metadata; + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataDynamic.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataDynamic.java (.../RowDataDynamic.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataDynamic.java (.../RowDataDynamic.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,33 +1,33 @@ /* - Copyright (C) 2002-2006 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.SQLException; -import com.mysql.jdbc.profiler.ProfileEventSink; +import com.mysql.jdbc.exceptions.MySQLQueryInterruptedException; import com.mysql.jdbc.profiler.ProfilerEvent; +import com.mysql.jdbc.profiler.ProfilerEventHandler; /** * Allows streaming of MySQL data. @@ -36,48 +36,44 @@ * @version $Id$ */ public class RowDataDynamic implements RowData { - // ~ Instance fields - // -------------------------------------------------------- - class OperationNotSupportedException extends SQLException { - OperationNotSupportedException() { - super( - Messages.getString("RowDataDynamic.10"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - } - private int columnCount; - private Field[] fields; + private Field[] metadata; private int index = -1; private MysqlIO io; private boolean isAfterEnd = false; - private boolean isAtEnd = false; + private boolean noMoreRows = false; private boolean isBinaryEncoded = false; - private Object[] nextRow; + private ResultSetRow nextRow; - private ResultSet owner; + private ResultSetImpl owner; private boolean streamerClosed = false; private boolean wasEmpty = false; // we don't know until we attempt to traverse - // ~ Methods - // ---------------------------------------------------------------- + private boolean useBufferRowExplicit; + private boolean moreResultsExisted; + + private ExceptionInterceptor exceptionInterceptor; + + private boolean isInterrupted = false; + /** * Creates a new RowDataDynamic object. * * @param io * the connection to MySQL that this data is coming from - * @param fields - * the fields that describe this data + * @param metadata + * the metadata that describe this data * @param isBinaryEncoded * is this data in native format? * @param colCount @@ -90,8 +86,9 @@ this.io = io; this.columnCount = colCount; this.isBinaryEncoded = isBinaryEncoded; - this.fields = fields; - nextRecord(); + this.metadata = fields; + this.exceptionInterceptor = this.io.getExceptionInterceptor(); + this.useBufferRowExplicit = MysqlIO.useBufferRowExplicit(this.metadata); } /** @@ -102,7 +99,7 @@ * @throws SQLException * if a database error occurs */ - public void addRow(byte[][] row) throws SQLException { + public void addRow(ResultSetRow row) throws SQLException { notSupported(); } @@ -143,61 +140,99 @@ * if a database error occurs */ public void close() throws SQLException { + // Belt and suspenders here - if we don't + // have a reference to the connection + // it's more than likely dead/gone and we + // won't be able to consume rows anyway + Object mutex = this; + + MySQLConnection conn = null; + + if (this.owner != null) { + conn = this.owner.connection; + + if (conn != null) { + mutex = conn.getConnectionMutex(); + } + } + boolean hadMore = false; int howMuchMore = 0; - // drain the rest of the records. - while (this.hasNext()) { - this.next(); - hadMore = true; - howMuchMore++; + synchronized (mutex) { + // drain the rest of the records. + while (next() != null) { + hadMore = true; + howMuchMore++; - if (howMuchMore % 100 == 0) { - Thread.yield(); + if (howMuchMore % 100 == 0) { + Thread.yield(); + } } - } - if (this.owner != null) { - Connection conn = this.owner.connection; + if (conn != null) { + if (!conn.getClobberStreamingResults() && + conn.getNetTimeoutForStreamingResults() > 0) { + String oldValue = conn + .getServerVariable("net_write_timeout"); - if (conn != null && conn.getUseUsageAdvisor()) { - if (hadMore) { + if (oldValue == null || oldValue.length() == 0) { + oldValue = "60"; // the current default + } - ProfileEventSink eventSink = ProfileEventSink - .getInstance(conn); + this.io.clearInputStream(); + + java.sql.Statement stmt = null; + + try { + stmt = conn.createStatement(); + ((com.mysql.jdbc.StatementImpl)stmt).executeSimpleNonQuery(conn, "SET net_write_timeout=" + oldValue); + } finally { + if (stmt != null) { + stmt.close(); + } + } + } + + if (conn.getUseUsageAdvisor()) { + if (hadMore) { - eventSink - .consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_WARN, - "", //$NON-NLS-1$ - this.owner.owningStatement == null ? "N/A" : this.owner.owningStatement.currentCatalog, //$NON-NLS-1$ - this.owner.connectionId, - this.owner.owningStatement == null ? -1 - : this.owner.owningStatement - .getId(), - -1, - System.currentTimeMillis(), - 0, - Constants.MILLIS_I18N, - null, - null, - Messages.getString("RowDataDynamic.2") //$NON-NLS-1$ - + howMuchMore - + Messages - .getString("RowDataDynamic.3") //$NON-NLS-1$ - + Messages - .getString("RowDataDynamic.4") //$NON-NLS-1$ - + Messages - .getString("RowDataDynamic.5") //$NON-NLS-1$ - + Messages - .getString("RowDataDynamic.6") //$NON-NLS-1$ - + this.owner.pointOfOrigin)); + ProfilerEventHandler eventSink = ProfilerEventHandlerFactory + .getInstance(conn); + + eventSink + .consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, + "", //$NON-NLS-1$ + this.owner.owningStatement == null ? "N/A" : this.owner.owningStatement.currentCatalog, //$NON-NLS-1$ + this.owner.connectionId, + this.owner.owningStatement == null ? -1 + : this.owner.owningStatement + .getId(), + -1, + System.currentTimeMillis(), + 0, + Constants.MILLIS_I18N, + null, + null, + Messages.getString("RowDataDynamic.2") //$NON-NLS-1$ + + howMuchMore + + Messages + .getString("RowDataDynamic.3") //$NON-NLS-1$ + + Messages + .getString("RowDataDynamic.4") //$NON-NLS-1$ + + Messages + .getString("RowDataDynamic.5") //$NON-NLS-1$ + + Messages + .getString("RowDataDynamic.6") //$NON-NLS-1$ + + this.owner.pointOfOrigin)); + } } } } - this.fields = null; + this.metadata = null; this.owner = null; } @@ -210,7 +245,7 @@ * @throws SQLException * if a database error occurs */ - public Object[] getAt(int ind) throws SQLException { + public ResultSetRow getAt(int ind) throws SQLException { notSupported(); return null; @@ -232,7 +267,7 @@ /** * @see com.mysql.jdbc.RowData#getOwner() */ - public ResultSet getOwner() { + public ResultSetInternalMethods getOwner() { return this.owner; } @@ -346,43 +381,55 @@ * @throws SQLException * if a database error occurs */ - public Object[] next() throws SQLException { - if (this.index != Integer.MAX_VALUE) { - this.index++; - } + public ResultSetRow next() throws SQLException { + - Object[] ret = this.nextRow; nextRecord(); - return ret; + if (this.nextRow == null && !this.streamerClosed && !this.moreResultsExisted) { + this.io.closeStreamer(this); + this.streamerClosed = true; + } + + if (this.nextRow != null) { + if (this.index != Integer.MAX_VALUE) { + this.index++; + } + } + + return this.nextRow; } private void nextRecord() throws SQLException { try { - if (!this.isAtEnd) { - - this.nextRow = this.io.nextRow(this.fields, this.columnCount, + if (!this.noMoreRows) { + this.nextRow = isInterrupted ? null : + this.io.nextRow(this.metadata, this.columnCount, this.isBinaryEncoded, - java.sql.ResultSet.CONCUR_READ_ONLY); + java.sql.ResultSet.CONCUR_READ_ONLY, true, + this.useBufferRowExplicit, true, null); if (this.nextRow == null) { - this.isAtEnd = true; - + this.noMoreRows = true; + this.isAfterEnd = true; + this.moreResultsExisted = this.io.tackOnMoreStreamingResults(this.owner); + if (this.index == -1) { this.wasEmpty = true; } } } else { this.isAfterEnd = true; } - } catch (CommunicationsException comEx) { - // Give a better error message - comEx.setWasStreamingResults(); - - throw comEx; } catch (SQLException sqlEx) { + if (sqlEx instanceof StreamingNotifiable) { + ((StreamingNotifiable)sqlEx).setWasStreamingResults(); + } else if (sqlEx instanceof MySQLQueryInterruptedException) { + this.isInterrupted = true; + } + // don't wrap SQLExceptions throw sqlEx; } catch (Exception ex) { @@ -392,10 +439,13 @@ exceptionMessage += Messages.getString("RowDataDynamic.7"); //$NON-NLS-1$ exceptionMessage += Util.stackTraceToString(ex); - throw new java.sql.SQLException( + SQLException sqlEx = SQLError.createSQLException( Messages.getString("RowDataDynamic.8") //$NON-NLS-1$ + exceptionType - + Messages.getString("RowDataDynamic.9") + exceptionMessage, SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$ + + Messages.getString("RowDataDynamic.9") + exceptionMessage, SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); //$NON-NLS-1$ + sqlEx.initCause(ex); + + throw sqlEx; } } @@ -415,9 +465,6 @@ notSupported(); } - // ~ Inner Classes - // ---------------------------------------------------------- - /** * Moves the current position in the result set to the given row number. * @@ -431,9 +478,9 @@ } /** - * @see com.mysql.jdbc.RowData#setOwner(com.mysql.jdbc.ResultSet) + * @see com.mysql.jdbc.RowData#setOwner(com.mysql.jdbc.ResultSetInternalMethods) */ - public void setOwner(ResultSet rs) { + public void setOwner(ResultSetImpl rs) { this.owner = rs; } @@ -449,7 +496,8 @@ public boolean wasEmpty() { return this.wasEmpty; } - - + public void setMetadata(Field[] metadata) { + this.metadata = metadata; + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataStatic.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataStatic.java (.../RowDataStatic.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/RowDataStatic.java (.../RowDataStatic.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,29 @@ /* - Copyright (C) 2002-2006 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import java.util.ArrayList; +import java.sql.SQLException; import java.util.List; /** @@ -34,19 +33,21 @@ * @version $Id$ */ public class RowDataStatic implements RowData { + private Field[] metadata; + private int index; - ResultSet owner; + ResultSetImpl owner; - private List rows; + private List rows; /** * Creates a new RowDataStatic object. * * @param rows * DOCUMENT ME! */ - public RowDataStatic(ArrayList rows) { + public RowDataStatic(List rows) { this.index = -1; this.rows = rows; } @@ -57,7 +58,7 @@ * @param row * DOCUMENT ME! */ - public void addRow(byte[][] row) { + public void addRow(ResultSetRow row) { this.rows.add(row); } @@ -96,12 +97,12 @@ * * @return DOCUMENT ME! */ - public Object[] getAt(int atIndex) { + public ResultSetRow getAt(int atIndex) throws SQLException { if ((atIndex < 0) || (atIndex >= this.rows.size())) { return null; } - return (Object[]) this.rows.get(atIndex); + return (this.rows.get(atIndex)).setMetadata(this.metadata); } /** @@ -116,7 +117,7 @@ /** * @see com.mysql.jdbc.RowData#getOwner() */ - public ResultSet getOwner() { + public ResultSetInternalMethods getOwner() { return this.owner; } @@ -208,11 +209,13 @@ * * @return DOCUMENT ME! */ - public Object[] next() { + public ResultSetRow next() throws SQLException { this.index++; if (this.index < this.rows.size()) { - return (Object[]) this.rows.get(this.index); + ResultSetRow row = this.rows.get(this.index); + + return row.setMetadata(this.metadata); } return null; @@ -239,9 +242,9 @@ } /** - * @see com.mysql.jdbc.RowData#setOwner(com.mysql.jdbc.ResultSet) + * @see com.mysql.jdbc.RowData#setOwner(com.mysql.jdbc.ResultSetInternalMethods) */ - public void setOwner(ResultSet rs) { + public void setOwner(ResultSetImpl rs) { this.owner = rs; } @@ -257,4 +260,8 @@ public boolean wasEmpty() { return (this.rows != null && this.rows.size() == 0); } + + public void setMetadata(Field[] metadata) { + this.metadata = metadata; + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/SQLError.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/SQLError.java (.../SQLError.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/SQLError.java (.../SQLError.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,139 +1,179 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.BindException; import java.sql.DataTruncation; import java.sql.SQLException; import java.sql.SQLWarning; - import java.util.HashMap; import java.util.Hashtable; -import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import com.mysql.jdbc.exceptions.MySQLDataException; import com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException; import com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException; +import com.mysql.jdbc.exceptions.MySQLQueryInterruptedException; import com.mysql.jdbc.exceptions.MySQLSyntaxErrorException; import com.mysql.jdbc.exceptions.MySQLTransactionRollbackException; +import com.mysql.jdbc.exceptions.MySQLTransientConnectionException; /** * SQLError is a utility class that maps MySQL error codes to X/Open error codes * as is required by the JDBC spec. * * @author Mark Matthews - * @version $Id$ */ public class SQLError { static final int ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196; - private static Map mysqlToSql99State; + private static Map mysqlToSql99State; - private static Map mysqlToSqlState; + private static Map mysqlToSqlState; + + // SQL-92 + public static final String SQL_STATE_WARNING = "01000"; + public static final String SQL_STATE_DISCONNECT_ERROR = "01002"; + public static final String SQL_STATE_DATE_TRUNCATED = "01004"; + public static final String SQL_STATE_PRIVILEGE_NOT_REVOKED = "01006"; + public static final String SQL_STATE_NO_DATA = "02000"; + public static final String SQL_STATE_WRONG_NO_OF_PARAMETERS = "07001"; + public static final String SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE = "08001"; + public static final String SQL_STATE_CONNECTION_IN_USE = "08002"; + public static final String SQL_STATE_CONNECTION_NOT_OPEN = "08003"; + public static final String SQL_STATE_CONNECTION_REJECTED = "08004"; + public static final String SQL_STATE_CONNECTION_FAILURE = "08006"; + public static final String SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN = "08007"; + public static final String SQL_STATE_COMMUNICATION_LINK_FAILURE = "08S01"; + public static final String SQL_STATE_FEATURE_NOT_SUPPORTED = "0A000"; + public static final String SQL_STATE_CARDINALITY_VIOLATION = "21000"; + public static final String SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST = "21S01"; + public static final String SQL_STATE_STRING_DATA_RIGHT_TRUNCATION = "22001"; + public static final String SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE = "22003"; + public static final String SQL_STATE_INVALID_DATETIME_FORMAT = "22007"; + public static final String SQL_STATE_DATETIME_FIELD_OVERFLOW = "22008"; + public static final String SQL_STATE_DIVISION_BY_ZERO = "22012"; + public static final String SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST = "22018"; + public static final String SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION = "23000"; + public static final String SQL_STATE_INVALID_CURSOR_STATE = "24000"; + public static final String SQL_STATE_INVALID_TRANSACTION_STATE = "25000"; + public static final String SQL_STATE_INVALID_AUTH_SPEC = "28000"; + public static final String SQL_STATE_INVALID_TRANSACTION_TERMINATION = "2D000"; + public static final String SQL_STATE_INVALID_CONDITION_NUMBER = "35000"; + public static final String SQL_STATE_INVALID_CATALOG_NAME = "3D000"; + public static final String SQL_STATE_ROLLBACK_SERIALIZATION_FAILURE = "40001"; + public static final String SQL_STATE_SYNTAX_ERROR = "42000"; + public static final String SQL_STATE_ER_TABLE_EXISTS_ERROR = "42S01"; + public static final String SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND = "42S02"; + public static final String SQL_STATE_ER_NO_SUCH_INDEX = "42S12"; + public static final String SQL_STATE_ER_DUP_FIELDNAME = "42S21"; + public static final String SQL_STATE_ER_BAD_FIELD_ERROR = "42S22"; + + // SQL-99 + public static final String SQL_STATE_INVALID_CONNECTION_ATTRIBUTE = "01S00"; + public static final String SQL_STATE_ERROR_IN_ROW = "01S01"; + public static final String SQL_STATE_NO_ROWS_UPDATED_OR_DELETED = "01S03"; + public static final String SQL_STATE_MORE_THAN_ONE_ROW_UPDATED_OR_DELETED = "01S04"; + public static final String SQL_STATE_RESIGNAL_WHEN_HANDLER_NOT_ACTIVE = "0K000"; + public static final String SQL_STATE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER = "0Z002"; + public static final String SQL_STATE_CASE_NOT_FOUND_FOR_CASE_STATEMENT = "20000"; + public static final String SQL_STATE_NULL_VALUE_NOT_ALLOWED = "22004"; + public static final String SQL_STATE_INVALID_LOGARITHM_ARGUMENT = "2201E"; + public static final String SQL_STATE_ACTIVE_SQL_TRANSACTION = "25001"; + public static final String SQL_STATE_READ_ONLY_SQL_TRANSACTION = "25006"; + public static final String SQL_STATE_SRE_PROHIBITED_SQL_STATEMENT_ATTEMPTED = "2F003"; + public static final String SQL_STATE_SRE_FUNCTION_EXECUTED_NO_RETURN_STATEMENT = "2F005"; + public static final String SQL_STATE_DEADLOCK = "41000"; // non-standard ? + public static final String SQL_STATE_ER_QUERY_INTERRUPTED = "70100"; // non-standard ? + public static final String SQL_STATE_BASE_TABLE_OR_VIEW_ALREADY_EXISTS = "S0001"; + public static final String SQL_STATE_BASE_TABLE_NOT_FOUND = "S0002"; + public static final String SQL_STATE_INDEX_ALREADY_EXISTS = "S0011"; + public static final String SQL_STATE_INDEX_NOT_FOUND = "S0012"; + public static final String SQL_STATE_COLUMN_ALREADY_EXISTS = "S0021"; + public static final String SQL_STATE_COLUMN_NOT_FOUND = "S0022"; + public static final String SQL_STATE_NO_DEFAULT_FOR_COLUMN = "S0023"; + public static final String SQL_STATE_GENERAL_ERROR = "S1000"; + public static final String SQL_STATE_MEMORY_ALLOCATION_FAILURE = "S1001"; + public static final String SQL_STATE_INVALID_COLUMN_NUMBER = "S1002"; + public static final String SQL_STATE_ILLEGAL_ARGUMENT = "S1009"; + public static final String SQL_STATE_DRIVER_NOT_CAPABLE = "S1C00"; + public static final String SQL_STATE_TIMEOUT_EXPIRED = "S1T00"; + public static final String SQL_STATE_CLI_SPECIFIC_CONDITION = "HY000"; + public static final String SQL_STATE_MEMORY_ALLOCATION_ERROR = "HY001"; + public static final String SQL_STATE_XA_RBROLLBACK = "XA100"; + public static final String SQL_STATE_XA_RBDEADLOCK = "XA102"; + public static final String SQL_STATE_XA_RBTIMEOUT = "XA106"; + public static final String SQL_STATE_XA_RMERR = "XAE03"; + public static final String SQL_STATE_XAER_NOTA = "XAE04"; + public static final String SQL_STATE_XAER_INVAL = "XAE05"; + public static final String SQL_STATE_XAER_RMFAIL = "XAE07"; + public static final String SQL_STATE_XAER_DUPID = "XAE08"; + public static final String SQL_STATE_XAER_OUTSIDE = "XAE09"; - public static final String SQL_STATE_BASE_TABLE_NOT_FOUND = "S0002"; //$NON-NLS-1$ + private static Map sqlStateMessages; - public static final String SQL_STATE_BASE_TABLE_OR_VIEW_ALREADY_EXISTS = "S0001"; //$NON-NLS-1$ + private static final long DEFAULT_WAIT_TIMEOUT_SECONDS = 28800; - public static final String SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND = "42S02"; //$NON-NLS-1$ + private static final int DUE_TO_TIMEOUT_FALSE = 0; - public static final String SQL_STATE_COLUMN_ALREADY_EXISTS = "S0021"; //$NON-NLS-1$ + private static final int DUE_TO_TIMEOUT_MAYBE = 2; - public static final String SQL_STATE_COLUMN_NOT_FOUND = "S0022"; //$NON-NLS-1$ - - public static final String SQL_STATE_COMMUNICATION_LINK_FAILURE = "08S01"; //$NON-NLS-1$ - - public static final String SQL_STATE_CONNECTION_FAIL_DURING_TX = "08007"; //$NON-NLS-1$ - - public static final String SQL_STATE_CONNECTION_IN_USE = "08002"; //$NON-NLS-1$ - - public static final String SQL_STATE_CONNECTION_NOT_OPEN = "08003"; //$NON-NLS-1$ - - public static final String SQL_STATE_CONNECTION_REJECTED = "08004"; //$NON-NLS-1$ - - public static final String SQL_STATE_DATE_TRUNCATED = "01004"; //$NON-NLS-1$ - - public static final String SQL_STATE_DATETIME_FIELD_OVERFLOW = "22008"; //$NON-NLS-1$ - - public static final String SQL_STATE_DEADLOCK = "41000"; //$NON-NLS-1$ - - public static final String SQL_STATE_DISCONNECT_ERROR = "01002"; //$NON-NLS-1$ - - public static final String SQL_STATE_DIVISION_BY_ZERO = "22012"; //$NON-NLS-1$ - - public static final String SQL_STATE_DRIVER_NOT_CAPABLE = "S1C00"; //$NON-NLS-1$ - - public static final String SQL_STATE_ERROR_IN_ROW = "01S01"; //$NON-NLS-1$ - - public static final String SQL_STATE_GENERAL_ERROR = "S1000"; //$NON-NLS-1$ - - public static final String SQL_STATE_ILLEGAL_ARGUMENT = "S1009"; //$NON-NLS-1$ - - public static final String SQL_STATE_INDEX_ALREADY_EXISTS = "S0011"; //$NON-NLS-1$ - - public static final String SQL_STATE_INDEX_NOT_FOUND = "S0012"; //$NON-NLS-1$ - - public static final String SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST = "21S01"; //$NON-NLS-1$ - - public static final String SQL_STATE_INVALID_AUTH_SPEC = "28000"; //$NON-NLS-1$ - - public static final String SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST = "22018"; // $NON_NLS-1$ - - public static final String SQL_STATE_INVALID_COLUMN_NUMBER = "S1002"; //$NON-NLS-1$ - - public static final String SQL_STATE_INVALID_CONNECTION_ATTRIBUTE = "01S00"; //$NON-NLS-1$ - - public static final String SQL_STATE_MEMORY_ALLOCATION_FAILURE = "S1001"; //$NON-NLS-1$ - - public static final String SQL_STATE_MORE_THAN_ONE_ROW_UPDATED_OR_DELETED = "01S04"; //$NON-NLS-1$ - - public static final String SQL_STATE_NO_DEFAULT_FOR_COLUMN = "S0023"; //$NON-NLS-1$ - - public static final String SQL_STATE_NO_ROWS_UPDATED_OR_DELETED = "01S03"; //$NON-NLS-1$ - - public static final String SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE = "22003"; //$NON-NLS-1$ - - public static final String SQL_STATE_PRIVILEGE_NOT_REVOKED = "01006"; //$NON-NLS-1$ - - public static final String SQL_STATE_SYNTAX_ERROR = "42000"; //$NON-NLS-1$ - - public static final String SQL_STATE_TIMEOUT_EXPIRED = "S1T00"; //$NON-NLS-1$ - - public static final String SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN = "08007"; // $NON_NLS-1$ - - public static final String SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE = "08001"; //$NON-NLS-1$ - - public static final String SQL_STATE_WRONG_NO_OF_PARAMETERS = "07001"; //$NON-NLS-1$ + private static final int DUE_TO_TIMEOUT_TRUE = 1; - public static final String SQL_STATE_INVALID_TRANSACTION_TERMINATION = "2D000"; //$NON_NLS-1$ - - private static Map sqlStateMessages; - + private static final Constructor JDBC_4_COMMUNICATIONS_EXCEPTION_CTOR; + + private static Method THROWABLE_INIT_CAUSE_METHOD; + static { - sqlStateMessages = new HashMap(); + if (Util.isJdbc4()) { + try { + JDBC_4_COMMUNICATIONS_EXCEPTION_CTOR = Class.forName( + "com.mysql.jdbc.exceptions.jdbc4.CommunicationsException") + .getConstructor( + new Class[] { MySQLConnection.class, Long.TYPE, Long.TYPE, Exception.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_COMMUNICATIONS_EXCEPTION_CTOR = null; + } + + try { + THROWABLE_INIT_CAUSE_METHOD = Throwable.class.getMethod("initCause", new Class[] {Throwable.class}); + } catch (Throwable t) { + // we're not on a VM that has it + THROWABLE_INIT_CAUSE_METHOD = null; + } + + sqlStateMessages = new HashMap(); sqlStateMessages.put(SQL_STATE_DISCONNECT_ERROR, Messages .getString("SQLError.35")); //$NON-NLS-1$ sqlStateMessages.put(SQL_STATE_DATE_TRUNCATED, Messages @@ -158,7 +198,7 @@ .getString("SQLError.45")); //$NON-NLS-1$ sqlStateMessages.put(SQL_STATE_CONNECTION_REJECTED, Messages .getString("SQLError.46")); //$NON-NLS-1$ - sqlStateMessages.put(SQL_STATE_CONNECTION_FAIL_DURING_TX, Messages + sqlStateMessages.put(SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN, Messages .getString("SQLError.47")); //$NON-NLS-1$ sqlStateMessages.put(SQL_STATE_COMMUNICATION_LINK_FAILURE, Messages .getString("SQLError.48")); //$NON-NLS-1$ @@ -205,438 +245,447 @@ sqlStateMessages.put(SQL_STATE_TIMEOUT_EXPIRED, Messages .getString("SQLError.69")); //$NON-NLS-1$ - mysqlToSqlState = new Hashtable(); + mysqlToSqlState = new Hashtable(); - // - // Communications Errors - // - // ER_CON_COUNT_ERROR 1040 - // ER_BAD_HOST_ERROR 1042 - // ER_HANDSHAKE_ERROR 1043 - // ER_UNKNOWN_COM_ERROR 1047 - // ER_IPSOCK_ERROR 1081 - // - mysqlToSqlState.put(new Integer(1040), SQL_STATE_CONNECTION_REJECTED); - mysqlToSqlState.put(new Integer(1042), SQL_STATE_CONNECTION_REJECTED); - mysqlToSqlState.put(new Integer(1043), SQL_STATE_CONNECTION_REJECTED); - mysqlToSqlState.put(new Integer(1047), - SQL_STATE_COMMUNICATION_LINK_FAILURE); - mysqlToSqlState.put(new Integer(1081), - SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SELECT_REDUCED, SQL_STATE_WARNING); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WARN_TOO_FEW_RECORDS, SQL_STATE_WARNING); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WARN_TOO_MANY_RECORDS, SQL_STATE_WARNING); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WARN_DATA_TRUNCATED, SQL_STATE_WARNING); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_UNINIT_VAR, SQL_STATE_WARNING); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SIGNAL_WARN, SQL_STATE_WARNING); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CON_COUNT_ERROR, SQL_STATE_CONNECTION_REJECTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NOT_SUPPORTED_AUTH_MODE, SQL_STATE_CONNECTION_REJECTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BAD_HOST_ERROR, SQL_STATE_CONNECTION_REJECTED); // legacy, should be SQL_STATE_COMMUNICATION_LINK_FAILURE + mysqlToSqlState.put(MysqlErrorNumbers.ER_HANDSHAKE_ERROR, SQL_STATE_CONNECTION_REJECTED); // legacy, should be SQL_STATE_COMMUNICATION_LINK_FAILURE + mysqlToSqlState.put(MysqlErrorNumbers.ER_HOST_IS_BLOCKED, SQL_STATE_CONNECTION_REJECTED); // overrides HY000, why? + mysqlToSqlState.put(MysqlErrorNumbers.ER_HOST_NOT_PRIVILEGED, SQL_STATE_CONNECTION_REJECTED); // overrides HY000, why? + mysqlToSqlState.put(MysqlErrorNumbers.ER_UNKNOWN_COM_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SERVER_SHUTDOWN, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_FORCING_CLOSE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_IPSOCK_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ABORTING_CONNECTION, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_PACKET_TOO_LARGE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_READ_ERROR_FROM_PIPE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_FCNTL_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_PACKETS_OUT_OF_ORDER, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_UNCOMPRESS_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_READ_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_READ_INTERRUPTED, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_ERROR_ON_WRITE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NET_WRITE_INTERRUPTED, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NEW_ABORTING_CONNECTION, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_MASTER_NET_READ, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_MASTER_NET_WRITE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CONNECT_TO_MASTER, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BADSELECT, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BADSTATEMENT, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_SUBSELECT_NYI, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_NO_RETSET, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ALTER_OPERATION_NOT_SUPPORTED, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DBACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BAD_DB_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_FIELD_WITH_GROUP, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_GROUP_FIELD, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_SUM_SELECT, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_LONG_IDENT, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_FIELDNAME, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_ER_DUP_FIELDNAME + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_KEYNAME, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_ENTRY, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_FIELD_SPEC, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_PARSE_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_EMPTY_QUERY, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NONUNIQ_TABLE, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_INVALID_DEFAULT, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_MULTIPLE_PRI_KEY, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_MANY_KEYS, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_MANY_KEY_PARTS, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_LONG_KEY, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_KEY_COLUMN_DOES_NOT_EXITS, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_BLOB_USED_AS_KEY, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_BIG_FIELDLENGTH, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_AUTO_KEY, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_SUCH_INDEX, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_ER_NO_SUCH_INDEX + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_FIELD_TERMINATORS, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_BLOBS_AND_NO_TERMINATED, SQL_STATE_ILLEGAL_ARGUMENT); // legacy, should be SQL_STATE_SYNTAX_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_CANT_REMOVE_ALL_FIELDS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CANT_DROP_FIELD_OR_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BLOB_CANT_HAVE_DEFAULT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_DB_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_TABLE_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_BIG_SELECT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UNKNOWN_PROCEDURE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_PARAMCOUNT_TO_PROCEDURE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_FIELD_SPECIFIED_TWICE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UNSUPPORTED_EXTENSION, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TABLE_MUST_HAVE_COLUMNS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UNKNOWN_CHARACTER_SET, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_BIG_ROWSIZE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_OUTER_JOIN, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NULL_COLUMN_IN_INDEX, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_PASSWORD_ANONYMOUS_USER, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_PASSWORD_NOT_ALLOWED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_PASSWORD_NO_MATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_REGEXP_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_MIX_OF_GROUP_FUNC_AND_FIELDS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NONEXISTING_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TABLEACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_COLUMNACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ILLEGAL_GRANT_FOR_TABLE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_GRANT_WRONG_HOST_OR_USER, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NONEXISTING_TABLE_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NOT_ALLOWED_COMMAND, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SYNTAX_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_LONG_STRING, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TABLE_CANT_HANDLE_BLOB, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_COLUMN_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_KEY_COLUMN, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BLOB_KEY_WITHOUT_LENGTH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_PRIMARY_CANT_HAVE_NULL, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_MANY_ROWS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_REQUIRES_PRIMARY_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_KEY_DOES_NOT_EXITS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CHECK_NO_SUCH_TABLE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CHECK_NOT_IMPLEMENTED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_MANY_USER_CONNECTIONS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_PERMISSION_TO_CREATE_USER, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_USER_LIMIT_REACHED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SPECIFIC_ACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_DEFAULT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_VALUE_FOR_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_TYPE_FOR_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CANT_USE_OPTION_HERE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NOT_SUPPORTED_YET, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_FK_DEF, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DERIVED_MUST_HAVE_ALIAS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TABLENAME_NOT_ALLOWED_HERE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SPATIAL_CANT_HAVE_NULL, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_COLLATION_CHARSET_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_NAME_FOR_INDEX, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_NAME_FOR_CATALOG, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UNKNOWN_STORAGE_ENGINE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_ALREADY_EXISTS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_DOES_NOT_EXIST, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_LILABEL_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_LABEL_REDEFINE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_LABEL_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BADRETURN, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UPDATE_LOG_DEPRECATED_IGNORED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UPDATE_LOG_DEPRECATED_TRANSLATED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_WRONG_NO_OF_ARGS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_COND_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_NORETURN, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BAD_CURSOR_QUERY, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BAD_CURSOR_SELECT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_CURSOR_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_UNDECLARED_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_DUP_PARAM, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_DUP_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_DUP_COND, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_DUP_CURS, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_VARCOND_AFTER_CURSHNDLR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_CURSOR_AFTER_HANDLER, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_PROCACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NONEXISTING_PROC_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BAD_SQLSTATE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CANT_CREATE_USER_WITH_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_DUP_HANDLER, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_NOT_VAR_ARG, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_BIG_SCALE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_BIG_PRECISION, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_M_BIGGER_THAN_D, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_LONG_BODY, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TOO_BIG_DISPLAYWIDTH, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_BAD_VAR_SHADOW, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_WRONG_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_NO_AGGREGATE, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_MAX_PREPARED_STMT_COUNT_REACHED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NON_GROUPING_FIELD_USED, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_PARAMETERS_TO_NATIVE_FCT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_PARAMETERS_TO_STORED_FCT, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_FUNC_INEXISTENT_NAME_COLLISION, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_SIGNAL_SET, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SPATIAL_MUST_HAVE_GEOM_COL, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TRUNCATE_ILLEGAL_FK, SQL_STATE_SYNTAX_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, SQL_STATE_CARDINALITY_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_OPERAND_COLUMNS, SQL_STATE_CARDINALITY_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SUBQUERY_NO_1_ROW, SQL_STATE_CARDINALITY_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_KEY, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BAD_NULL_ERROR, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NON_UNIQ_ERROR, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_UNIQUE, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_REFERENCED_ROW, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ROW_IS_REFERENCED, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ROW_IS_REFERENCED_2, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_REFERENCED_ROW_2, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_FOREIGN_DUPLICATE_KEY, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_ENTRY_WITH_KEY_NAME, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DUP_UNKNOWN_IN_INDEX, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DATA_TOO_LONG, SQL_STATE_STRING_DATA_RIGHT_TRUNCATION); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WARN_DATA_OUT_OF_RANGE, SQL_STATE_WARNING); // legacy, should be SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE + mysqlToSqlState.put(MysqlErrorNumbers.ER_CANT_CREATE_GEOMETRY_OBJECT, SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DATA_OUT_OF_RANGE, SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TRUNCATED_WRONG_VALUE, SQL_STATE_INVALID_DATETIME_FORMAT); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ILLEGAL_VALUE_FOR_TYPE, SQL_STATE_INVALID_DATETIME_FORMAT); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DATETIME_FUNCTION_OVERFLOW, SQL_STATE_DATETIME_FIELD_OVERFLOW); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DIVISION_BY_ZERO, SQL_STATE_DIVISION_BY_ZERO); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_CURSOR_ALREADY_OPEN, SQL_STATE_INVALID_CURSOR_STATE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_SP_CURSOR_NOT_OPEN, SQL_STATE_INVALID_CURSOR_STATE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_CANT_DO_THIS_DURING_AN_TRANSACTION, SQL_STATE_INVALID_TRANSACTION_STATE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_READ_ONLY_TRANSACTION, SQL_STATE_INVALID_TRANSACTION_STATE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR, SQL_STATE_INVALID_AUTH_SPEC); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ACCESS_DENIED_NO_PASSWORD_ERROR, SQL_STATE_INVALID_AUTH_SPEC); + mysqlToSqlState.put(MysqlErrorNumbers.ER_ACCESS_DENIED_CHANGE_USER_ERROR, SQL_STATE_INVALID_AUTH_SPEC); + mysqlToSqlState.put(MysqlErrorNumbers.ER_DA_INVALID_CONDITION_NUMBER, SQL_STATE_INVALID_CONDITION_NUMBER); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_DB_ERROR, SQL_STATE_INVALID_CATALOG_NAME); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_VALUE_COUNT, SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST); + mysqlToSqlState.put(MysqlErrorNumbers.ER_WRONG_VALUE_COUNT_ON_ROW, SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST); + mysqlToSqlState.put(MysqlErrorNumbers.ER_TABLE_EXISTS_ERROR, SQL_STATE_ER_TABLE_EXISTS_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BAD_TABLE_ERROR, SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); + mysqlToSqlState.put(MysqlErrorNumbers.ER_UNKNOWN_TABLE, SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); + mysqlToSqlState.put(MysqlErrorNumbers.ER_NO_SUCH_TABLE, SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); + mysqlToSqlState.put(MysqlErrorNumbers.ER_BAD_FIELD_ERROR, SQL_STATE_COLUMN_NOT_FOUND); // legacy, should be SQL_STATE_ER_BAD_FIELD_ERROR + mysqlToSqlState.put(MysqlErrorNumbers.ER_ILLEGAL_REFERENCE, SQL_STATE_ER_BAD_FIELD_ERROR); + mysqlToSqlState.put(MysqlErrorNumbers.ER_OUTOFMEMORY, SQL_STATE_MEMORY_ALLOCATION_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_OUT_OF_SORTMEMORY, SQL_STATE_MEMORY_ALLOCATION_FAILURE); + mysqlToSqlState.put(MysqlErrorNumbers.ER_LOCK_WAIT_TIMEOUT, SQL_STATE_DEADLOCK); // overrides HY000, why? + mysqlToSqlState.put(MysqlErrorNumbers.ER_LOCK_DEADLOCK, SQL_STATE_DEADLOCK); // legacy, should be SQL_STATE_ROLLBACK_SERIALIZATION_FAILURE - // ER_HOST_IS_BLOCKED 1129 - // ER_HOST_NOT_PRIVILEGED 1130 - mysqlToSqlState.put(new Integer(1129), SQL_STATE_CONNECTION_REJECTED); - mysqlToSqlState.put(new Integer(1130), SQL_STATE_CONNECTION_REJECTED); + mysqlToSql99State = new HashMap(); - // - // Authentication Errors - // - // ER_ACCESS_DENIED_ERROR 1045 - // - mysqlToSqlState.put(new Integer(1045), SQL_STATE_INVALID_AUTH_SPEC); - - // - // Resource errors - // - // ER_CANT_CREATE_FILE 1004 - // ER_CANT_CREATE_TABLE 1005 - // ER_CANT_LOCK 1015 - // ER_DISK_FULL 1021 - // ER_CON_COUNT_ERROR 1040 - // ER_OUT_OF_RESOURCES 1041 - // - // Out-of-memory errors - // - // ER_OUTOFMEMORY 1037 - // ER_OUT_OF_SORTMEMORY 1038 - // - mysqlToSqlState.put(new Integer(1037), - SQL_STATE_MEMORY_ALLOCATION_FAILURE); - mysqlToSqlState.put(new Integer(1038), - SQL_STATE_MEMORY_ALLOCATION_FAILURE); - - // - // Syntax Errors - // - // ER_PARSE_ERROR 1064 - // ER_EMPTY_QUERY 1065 - // - mysqlToSqlState.put(new Integer(1064), SQL_STATE_SYNTAX_ERROR); - mysqlToSqlState.put(new Integer(1065), SQL_STATE_SYNTAX_ERROR); - - // - // Invalid argument errors - // - // ER_WRONG_FIELD_WITH_GROUP 1055 - // ER_WRONG_GROUP_FIELD 1056 - // ER_WRONG_SUM_SELECT 1057 - // ER_TOO_LONG_IDENT 1059 - // ER_DUP_FIELDNAME 1060 - // ER_DUP_KEYNAME 1061 - // ER_DUP_ENTRY 1062 - // ER_WRONG_FIELD_SPEC 1063 - // ER_NONUNIQ_TABLE 1066 - // ER_INVALID_DEFAULT 1067 - // ER_MULTIPLE_PRI_KEY 1068 - // ER_TOO_MANY_KEYS 1069 - // ER_TOO_MANY_KEY_PARTS 1070 - // ER_TOO_LONG_KEY 1071 - // ER_KEY_COLUMN_DOES_NOT_EXIST 1072 - // ER_BLOB_USED_AS_KEY 1073 - // ER_TOO_BIG_FIELDLENGTH 1074 - // ER_WRONG_AUTO_KEY 1075 - // ER_NO_SUCH_INDEX 1082 - // ER_WRONG_FIELD_TERMINATORS 1083 - // ER_BLOBS_AND_NO_TERMINATED 1084 - // - mysqlToSqlState.put(new Integer(1055), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1056), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1057), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1059), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1060), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1061), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1062), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1063), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1066), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1067), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1068), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1069), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1070), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1071), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1072), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1073), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1074), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1075), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1082), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1083), SQL_STATE_ILLEGAL_ARGUMENT); - mysqlToSqlState.put(new Integer(1084), SQL_STATE_ILLEGAL_ARGUMENT); - - // - // ER_WRONG_VALUE_COUNT 1058 - // - mysqlToSqlState.put(new Integer(1058), - SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST); - - // ER_CANT_CREATE_DB 1006 - // ER_DB_CREATE_EXISTS 1007 - // ER_DB_DROP_EXISTS 1008 - // ER_DB_DROP_DELETE 1009 - // ER_DB_DROP_RMDIR 1010 - // ER_CANT_DELETE_FILE 1011 - // ER_CANT_FIND_SYSTEM_REC 1012 - // ER_CANT_GET_STAT 1013 - // ER_CANT_GET_WD 1014 - // ER_UNEXPECTED_EOF 1039 - // ER_CANT_OPEN_FILE 1016 - // ER_FILE_NOT_FOUND 1017 - // ER_CANT_READ_DIR 1018 - // ER_CANT_SET_WD 1019 - // ER_CHECKREAD 1020 - // ER_DUP_KEY 1022 - // ER_ERROR_ON_CLOSE 1023 - // ER_ERROR_ON_READ 1024 - // ER_ERROR_ON_RENAME 1025 - // ER_ERROR_ON_WRITE 1026 - // ER_FILE_USED 1027 - // ER_FILSORT_ABORT 1028 - // ER_FORM_NOT_FOUND 1029 - // ER_GET_ERRNO 1030 - // ER_ILLEGAL_HA 1031 - // ER_KEY_NOT_FOUND 1032 - // ER_NOT_FORM_FILE 1033 - // ER_DBACCESS_DENIED_ERROR 1044 - // ER_NO_DB_ERROR 1046 - // ER_BAD_NULL_ERROR 1048 - // ER_BAD_DB_ERROR 1049 - // ER_TABLE_EXISTS_ERROR 1050 - // ER_BAD_TABLE_ERROR 1051 - mysqlToSqlState.put(new Integer(1051), - SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); - - // ER_NON_UNIQ_ERROR 1052 - // ER_BAD_FIELD_ERROR 1054 - mysqlToSqlState.put(new Integer(1054), SQL_STATE_COLUMN_NOT_FOUND); - - // ER_TEXTFILE_NOT_READABLE 1085 - // ER_FILE_EXISTS_ERROR 1086 - // ER_LOAD_INFO 1087 - // ER_ALTER_INFO 1088 - // ER_WRONG_SUB_KEY 1089 - // ER_CANT_REMOVE_ALL_FIELDS 1090 - // ER_CANT_DROP_FIELD_OR_KEY 1091 - // ER_INSERT_INFO 1092 - // ER_INSERT_TABLE_USED 1093 - // ER_LOCK_DEADLOCK 1213 - mysqlToSqlState.put(new Integer(1205), SQL_STATE_DEADLOCK); - mysqlToSqlState.put(new Integer(1213), SQL_STATE_DEADLOCK); - - mysqlToSql99State = new HashMap(); - - mysqlToSql99State.put(new Integer(1205), SQL_STATE_DEADLOCK); - mysqlToSql99State.put(new Integer(1213), SQL_STATE_DEADLOCK); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_DUP_KEY), - "23000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_OUTOFMEMORY), - "HY001"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_OUT_OF_SORTMEMORY), "HY001"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_CON_COUNT_ERROR), "08004"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_BAD_HOST_ERROR), - "08S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_HANDSHAKE_ERROR), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_DBACCESS_DENIED_ERROR), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR), "28000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TABLE_EXISTS_ERROR), "42S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_BAD_TABLE_ERROR), "42S02"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_NON_UNIQ_ERROR), - "23000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_SERVER_SHUTDOWN), "08S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_BAD_FIELD_ERROR), "42S22"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_FIELD_WITH_GROUP), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_GROUP_FIELD), "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_WRONG_SUM_SELECT), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_VALUE_COUNT), "21S01"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_TOO_LONG_IDENT), - "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_DUP_FIELDNAME), - "42S21"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_DUP_KEYNAME), - "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_DUP_ENTRY), - "23000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_WRONG_FIELD_SPEC), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_PARSE_ERROR), - "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_EMPTY_QUERY), - "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_NONUNIQ_TABLE), - "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_INVALID_DEFAULT), "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_MULTIPLE_PRI_KEY), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_TOO_MANY_KEYS), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TOO_MANY_KEY_PARTS), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_TOO_LONG_KEY), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_KEY_COLUMN_DOES_NOT_EXITS), "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_BLOB_USED_AS_KEY), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TOO_BIG_FIELDLENGTH), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_WRONG_AUTO_KEY), - "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_FORCING_CLOSE), - "08S01"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_IPSOCK_ERROR), - "08S01"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_NO_SUCH_INDEX), - "42S12"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_FIELD_TERMINATORS), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_BLOBS_AND_NO_TERMINATED), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CANT_REMOVE_ALL_FIELDS), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CANT_DROP_FIELD_OR_KEY), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_BLOB_CANT_HAVE_DEFAULT), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_WRONG_DB_NAME), - "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_WRONG_TABLE_NAME), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_TOO_BIG_SELECT), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_UNKNOWN_PROCEDURE), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_PARAMCOUNT_TO_PROCEDURE), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_UNKNOWN_TABLE), - "42S02"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_FIELD_SPECIFIED_TWICE), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_UNSUPPORTED_EXTENSION), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TABLE_MUST_HAVE_COLUMNS), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_UNKNOWN_CHARACTER_SET), "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_TOO_BIG_ROWSIZE), "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_WRONG_OUTER_JOIN), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NULL_COLUMN_IN_INDEX), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_PASSWORD_ANONYMOUS_USER), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_PASSWORD_NOT_ALLOWED), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_PASSWORD_NO_MATCH), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_VALUE_COUNT_ON_ROW), "21S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_INVALID_USE_OF_NULL), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_REGEXP_ERROR), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_MIX_OF_GROUP_FUNC_AND_FIELDS), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NONEXISTING_GRANT), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TABLEACCESS_DENIED_ERROR), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_COLUMNACCESS_DENIED_ERROR), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_ILLEGAL_GRANT_FOR_TABLE), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_GRANT_WRONG_HOST_OR_USER), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_NO_SUCH_TABLE), - "42S02"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NONEXISTING_TABLE_GRANT), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NOT_ALLOWED_COMMAND), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_SYNTAX_ERROR), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_ABORTING_CONNECTION), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_PACKET_TOO_LARGE), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_READ_ERROR_FROM_PIPE), "08S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_NET_FCNTL_ERROR), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_PACKETS_OUT_OF_ORDER), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_UNCOMPRESS_ERROR), "08S01"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_NET_READ_ERROR), - "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_READ_INTERRUPTED), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_ERROR_ON_WRITE), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NET_WRITE_INTERRUPTED), "08S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_TOO_LONG_STRING), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TABLE_CANT_HANDLE_BLOB), "42000"); - mysqlToSql99State - .put(new Integer( - MysqlErrorNumbers.ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_COLUMN_NAME), "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_WRONG_KEY_COLUMN), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_DUP_UNIQUE), - "23000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_BLOB_KEY_WITHOUT_LENGTH), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_PRIMARY_CANT_HAVE_NULL), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_TOO_MANY_ROWS), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_REQUIRES_PRIMARY_KEY), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CHECK_NO_SUCH_TABLE), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CHECK_NOT_IMPLEMENTED), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CANT_DO_THIS_DURING_AN_TRANSACTION), - "25000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NEW_ABORTING_CONNECTION), "08S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_MASTER_NET_READ), "08S01"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_MASTER_NET_WRITE), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TOO_MANY_USER_CONNECTIONS), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_READ_ONLY_TRANSACTION), "25000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NO_PERMISSION_TO_CREATE_USER), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_LOCK_DEADLOCK), - "40001"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NO_REFERENCED_ROW), "23000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_ROW_IS_REFERENCED), "23000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CONNECT_TO_MASTER), "08S01"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), - "21000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_USER_LIMIT_REACHED), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_NO_DEFAULT), - "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_VALUE_FOR_VAR), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_TYPE_FOR_VAR), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_CANT_USE_OPTION_HERE), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NOT_SUPPORTED_YET), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_WRONG_FK_DEF), - "42000"); - mysqlToSql99State.put( - new Integer(MysqlErrorNumbers.ER_OPERAND_COLUMNS), "21000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_SUBQUERY_NO_1_ROW), "21000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_ILLEGAL_REFERENCE), "42S22"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_DERIVED_MUST_HAVE_ALIAS), "42000"); - mysqlToSql99State.put(new Integer(MysqlErrorNumbers.ER_SELECT_REDUCED), - "01000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_TABLENAME_NOT_ALLOWED_HERE), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_NOT_SUPPORTED_AUTH_MODE), "08004"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_SPATIAL_CANT_HAVE_NULL), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_COLLATION_CHARSET_MISMATCH), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WARN_TOO_FEW_RECORDS), "01000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WARN_TOO_MANY_RECORDS), "01000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WARN_NULL_TO_NOTNULL), "01000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WARN_DATA_OUT_OF_RANGE), "01000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WARN_DATA_TRUNCATED), "01000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_NAME_FOR_INDEX), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_WRONG_NAME_FOR_CATALOG), "42000"); - mysqlToSql99State.put(new Integer( - MysqlErrorNumbers.ER_UNKNOWN_STORAGE_ENGINE), "42000"); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SELECT_REDUCED, SQL_STATE_WARNING); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WARN_TOO_FEW_RECORDS, SQL_STATE_WARNING); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WARN_TOO_MANY_RECORDS, SQL_STATE_WARNING); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WARN_DATA_TRUNCATED, SQL_STATE_WARNING); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WARN_NULL_TO_NOTNULL, SQL_STATE_WARNING); // legacy, should be SQL_STATE_NULL_VALUE_NOT_ALLOWED + mysqlToSql99State.put(MysqlErrorNumbers.ER_WARN_DATA_OUT_OF_RANGE, SQL_STATE_WARNING); // legacy, should be SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_UNINIT_VAR, SQL_STATE_WARNING); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SIGNAL_WARN, SQL_STATE_WARNING); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_FETCH_NO_DATA, SQL_STATE_NO_DATA); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SIGNAL_NOT_FOUND, SQL_STATE_NO_DATA); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CON_COUNT_ERROR, SQL_STATE_CONNECTION_REJECTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NOT_SUPPORTED_AUTH_MODE, SQL_STATE_CONNECTION_REJECTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BAD_HOST_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_HANDSHAKE_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UNKNOWN_COM_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SERVER_SHUTDOWN, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_FORCING_CLOSE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_IPSOCK_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ABORTING_CONNECTION, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_PACKET_TOO_LARGE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_READ_ERROR_FROM_PIPE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_FCNTL_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_PACKETS_OUT_OF_ORDER, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_UNCOMPRESS_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_READ_ERROR, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_READ_INTERRUPTED, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_ERROR_ON_WRITE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NET_WRITE_INTERRUPTED, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NEW_ABORTING_CONNECTION, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_MASTER_NET_READ, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_MASTER_NET_WRITE, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CONNECT_TO_MASTER, SQL_STATE_COMMUNICATION_LINK_FAILURE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BADSELECT, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BADSTATEMENT, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_SUBSELECT_NYI, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_NO_RETSET, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ALTER_OPERATION_NOT_SUPPORTED, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, SQL_STATE_FEATURE_NOT_SUPPORTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DBACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BAD_DB_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_FIELD_WITH_GROUP, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_GROUP_FIELD, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_SUM_SELECT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_LONG_IDENT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_KEYNAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_FIELD_SPEC, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_PARSE_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_EMPTY_QUERY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NONUNIQ_TABLE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_INVALID_DEFAULT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_MULTIPLE_PRI_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_MANY_KEYS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_MANY_KEY_PARTS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_LONG_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_KEY_COLUMN_DOES_NOT_EXITS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BLOB_USED_AS_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_BIG_FIELDLENGTH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_AUTO_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_FIELD_TERMINATORS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BLOBS_AND_NO_TERMINATED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_REMOVE_ALL_FIELDS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_DROP_FIELD_OR_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BLOB_CANT_HAVE_DEFAULT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_DB_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_TABLE_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_BIG_SELECT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UNKNOWN_PROCEDURE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_PARAMCOUNT_TO_PROCEDURE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_FIELD_SPECIFIED_TWICE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UNSUPPORTED_EXTENSION, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TABLE_MUST_HAVE_COLUMNS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UNKNOWN_CHARACTER_SET, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_BIG_ROWSIZE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_OUTER_JOIN, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NULL_COLUMN_IN_INDEX, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_PASSWORD_ANONYMOUS_USER, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_PASSWORD_NOT_ALLOWED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_PASSWORD_NO_MATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_REGEXP_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_MIX_OF_GROUP_FUNC_AND_FIELDS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NONEXISTING_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TABLEACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_COLUMNACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ILLEGAL_GRANT_FOR_TABLE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_GRANT_WRONG_HOST_OR_USER, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NONEXISTING_TABLE_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NOT_ALLOWED_COMMAND, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SYNTAX_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_LONG_STRING, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TABLE_CANT_HANDLE_BLOB, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_COLUMN_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_KEY_COLUMN, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BLOB_KEY_WITHOUT_LENGTH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_PRIMARY_CANT_HAVE_NULL, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_MANY_ROWS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_REQUIRES_PRIMARY_KEY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_KEY_DOES_NOT_EXITS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CHECK_NO_SUCH_TABLE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CHECK_NOT_IMPLEMENTED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_MANY_USER_CONNECTIONS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_PERMISSION_TO_CREATE_USER, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_USER_LIMIT_REACHED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SPECIFIC_ACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_DEFAULT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_VALUE_FOR_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_TYPE_FOR_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_USE_OPTION_HERE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NOT_SUPPORTED_YET, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_FK_DEF, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DERIVED_MUST_HAVE_ALIAS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TABLENAME_NOT_ALLOWED_HERE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SPATIAL_CANT_HAVE_NULL, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_COLLATION_CHARSET_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_NAME_FOR_INDEX, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_NAME_FOR_CATALOG, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UNKNOWN_STORAGE_ENGINE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_ALREADY_EXISTS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_DOES_NOT_EXIST, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_LILABEL_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_LABEL_REDEFINE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_LABEL_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BADRETURN, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UPDATE_LOG_DEPRECATED_IGNORED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UPDATE_LOG_DEPRECATED_TRANSLATED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_WRONG_NO_OF_ARGS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_COND_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_NORETURN, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BAD_CURSOR_QUERY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BAD_CURSOR_SELECT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_CURSOR_MISMATCH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_UNDECLARED_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_DUP_PARAM, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_DUP_VAR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_DUP_COND, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_DUP_CURS, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_VARCOND_AFTER_CURSHNDLR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_CURSOR_AFTER_HANDLER, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_PROCACCESS_DENIED_ERROR, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NONEXISTING_PROC_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BAD_SQLSTATE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_CREATE_USER_WITH_GRANT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_DUP_HANDLER, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_NOT_VAR_ARG, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_BIG_SCALE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_BIG_PRECISION, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_M_BIGGER_THAN_D, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_LONG_BODY, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TOO_BIG_DISPLAYWIDTH, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_BAD_VAR_SHADOW, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_WRONG_NAME, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_NO_AGGREGATE, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_MAX_PREPARED_STMT_COUNT_REACHED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NON_GROUPING_FIELD_USED, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_PARAMETERS_TO_NATIVE_FCT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_PARAMETERS_TO_STORED_FCT, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_FUNC_INEXISTENT_NAME_COLLISION, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_SIGNAL_SET, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SPATIAL_MUST_HAVE_GEOM_COL, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TRUNCATE_ILLEGAL_FK, SQL_STATE_SYNTAX_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, SQL_STATE_CARDINALITY_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_OPERAND_COLUMNS, SQL_STATE_CARDINALITY_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SUBQUERY_NO_1_ROW, SQL_STATE_CARDINALITY_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_KEY, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BAD_NULL_ERROR, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NON_UNIQ_ERROR, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_ENTRY, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_UNIQUE, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_REFERENCED_ROW, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ROW_IS_REFERENCED, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ROW_IS_REFERENCED_2, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_REFERENCED_ROW_2, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_FOREIGN_DUPLICATE_KEY, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_ENTRY_WITH_KEY_NAME, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_UNKNOWN_IN_INDEX, SQL_STATE_INTEGRITY_CONSTRAINT_VIOLATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DATA_TOO_LONG, SQL_STATE_STRING_DATA_RIGHT_TRUNCATION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_CREATE_GEOMETRY_OBJECT, SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DATA_OUT_OF_RANGE, SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TRUNCATED_WRONG_VALUE, SQL_STATE_INVALID_DATETIME_FORMAT); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ILLEGAL_VALUE_FOR_TYPE, SQL_STATE_INVALID_DATETIME_FORMAT); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DATETIME_FUNCTION_OVERFLOW, SQL_STATE_DATETIME_FIELD_OVERFLOW); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DIVISION_BY_ZERO, SQL_STATE_DIVISION_BY_ZERO); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_CURSOR_ALREADY_OPEN, SQL_STATE_INVALID_CURSOR_STATE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_CURSOR_NOT_OPEN, SQL_STATE_INVALID_CURSOR_STATE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_DO_THIS_DURING_AN_TRANSACTION, SQL_STATE_INVALID_TRANSACTION_STATE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_READ_ONLY_TRANSACTION, SQL_STATE_INVALID_TRANSACTION_STATE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR, SQL_STATE_INVALID_AUTH_SPEC); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ACCESS_DENIED_NO_PASSWORD_ERROR, SQL_STATE_INVALID_AUTH_SPEC); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ACCESS_DENIED_CHANGE_USER_ERROR, SQL_STATE_INVALID_AUTH_SPEC); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DA_INVALID_CONDITION_NUMBER, SQL_STATE_INVALID_CONDITION_NUMBER); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_DB_ERROR, SQL_STATE_INVALID_CATALOG_NAME); + mysqlToSql99State.put(MysqlErrorNumbers.ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER, SQL_STATE_RESIGNAL_WHEN_HANDLER_NOT_ACTIVE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER, SQL_STATE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_CASE_NOT_FOUND, SQL_STATE_CASE_NOT_FOUND_FOR_CASE_STATEMENT); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_VALUE_COUNT, SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST); + mysqlToSql99State.put(MysqlErrorNumbers.ER_WRONG_VALUE_COUNT_ON_ROW, SQL_STATE_INSERT_VALUE_LIST_NO_MATCH_COL_LIST); + mysqlToSql99State.put(MysqlErrorNumbers.ER_INVALID_USE_OF_NULL, SQL_STATE_SYNTAX_ERROR); // legacy, must be SQL_STATE_NULL_VALUE_NOT_ALLOWED + mysqlToSql99State.put(MysqlErrorNumbers.ER_INVALID_ARGUMENT_FOR_LOGARITHM, SQL_STATE_INVALID_LOGARITHM_ARGUMENT); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_CHANGE_TX_ISOLATION, SQL_STATE_ACTIVE_SQL_TRANSACTION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, SQL_STATE_READ_ONLY_SQL_TRANSACTION); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_NO_RECURSIVE_CREATE, SQL_STATE_SRE_PROHIBITED_SQL_STATEMENT_ATTEMPTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_SP_NORETURNEND, SQL_STATE_SRE_FUNCTION_EXECUTED_NO_RETURN_STATEMENT); + mysqlToSql99State.put(MysqlErrorNumbers.ER_TABLE_EXISTS_ERROR, SQL_STATE_ER_TABLE_EXISTS_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BAD_TABLE_ERROR, SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); + mysqlToSql99State.put(MysqlErrorNumbers.ER_UNKNOWN_TABLE, SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_SUCH_TABLE, SQL_STATE_BASE_TABLE_OR_VIEW_NOT_FOUND); + mysqlToSql99State.put(MysqlErrorNumbers.ER_NO_SUCH_INDEX, SQL_STATE_ER_NO_SUCH_INDEX); + mysqlToSql99State.put(MysqlErrorNumbers.ER_DUP_FIELDNAME, SQL_STATE_ER_DUP_FIELDNAME); + mysqlToSql99State.put(MysqlErrorNumbers.ER_BAD_FIELD_ERROR, SQL_STATE_ER_BAD_FIELD_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_ILLEGAL_REFERENCE, SQL_STATE_ER_BAD_FIELD_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_QUERY_INTERRUPTED, SQL_STATE_ER_QUERY_INTERRUPTED); + mysqlToSql99State.put(MysqlErrorNumbers.ER_OUTOFMEMORY, SQL_STATE_MEMORY_ALLOCATION_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_OUT_OF_SORTMEMORY, SQL_STATE_MEMORY_ALLOCATION_ERROR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XA_RBROLLBACK, SQL_STATE_XA_RBROLLBACK); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XA_RBDEADLOCK, SQL_STATE_XA_RBDEADLOCK); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XA_RBTIMEOUT, SQL_STATE_XA_RBTIMEOUT); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XA_RMERR, SQL_STATE_XA_RMERR); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XAER_NOTA, SQL_STATE_XAER_NOTA); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XAER_INVAL, SQL_STATE_XAER_INVAL); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XAER_RMFAIL, SQL_STATE_XAER_RMFAIL); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XAER_DUPID, SQL_STATE_XAER_DUPID); + mysqlToSql99State.put(MysqlErrorNumbers.ER_XAER_OUTSIDE, SQL_STATE_XAER_OUTSIDE); + mysqlToSql99State.put(MysqlErrorNumbers.ER_LOCK_WAIT_TIMEOUT, SQL_STATE_DEADLOCK); // overriding HY000, why? + mysqlToSql99State.put(MysqlErrorNumbers.ER_LOCK_DEADLOCK, SQL_STATE_DEADLOCK); // legacy, should be SQL_STATE_ROLLBACK_SERIALIZATION_FAILURE } /** @@ -713,9 +762,9 @@ int code = warnRs.getInt("Code"); //$NON-NLS-1$ if (forTruncationOnly) { - if (code == 1265 || code == 1264) { + if (code == MysqlErrorNumbers.ER_WARN_DATA_TRUNCATED || code == MysqlErrorNumbers.ER_WARN_DATA_OUT_OF_RANGE) { DataTruncation newTruncation = new MysqlDataTruncation( - warnRs.getString("Message"), 0, false, false, 0, 0); //$NON-NLS-1$ + warnRs.getString("Message"), 0, false, false, 0, 0, code); //$NON-NLS-1$ if (currentWarning == null) { currentWarning = newTruncation; @@ -724,7 +773,7 @@ } } } else { - String level = warnRs.getString("Level"); //$NON-NLS-1$ + //String level = warnRs.getString("Level"); //$NON-NLS-1$ String message = warnRs.getString("Message"); //$NON-NLS-1$ SQLWarning newWarning = new SQLWarning(message, SQLError @@ -773,24 +822,20 @@ } public static void dumpSqlStatesMappingsAsXml() throws Exception { - TreeMap allErrorNumbers = new TreeMap(); - Map mysqlErrorNumbersToNames = new HashMap(); + TreeMap allErrorNumbers = new TreeMap(); + Map mysqlErrorNumbersToNames = new HashMap(); - Integer errorNumber = null; +// Integer errorNumber = null; // // First create a list of all 'known' error numbers that // are mapped. // - for (Iterator mysqlErrorNumbers = mysqlToSql99State.keySet().iterator(); mysqlErrorNumbers - .hasNext();) { - errorNumber = (Integer) mysqlErrorNumbers.next(); + for (Integer errorNumber : mysqlToSql99State.keySet()) { allErrorNumbers.put(errorNumber, errorNumber); } - for (Iterator mysqlErrorNumbers = mysqlToSqlState.keySet().iterator(); mysqlErrorNumbers - .hasNext();) { - errorNumber = (Integer) mysqlErrorNumbers.next(); + for (Integer errorNumber : mysqlToSqlState.keySet()) { allErrorNumbers.put(errorNumber, errorNumber); } @@ -811,10 +856,7 @@ System.out.println(""); - for (Iterator allErrorNumbersIter = allErrorNumbers.keySet().iterator(); allErrorNumbersIter - .hasNext();) { - errorNumber = (Integer) allErrorNumbersIter.next(); - + for (Integer errorNumber : allErrorNumbers.keySet()) { String sql92State = mysqlToSql99(errorNumber.intValue()); String oldSqlState = mysqlToXOpen(errorNumber.intValue()); @@ -831,17 +873,17 @@ } static String get(String stateCode) { - return (String) sqlStateMessages.get(stateCode); + return sqlStateMessages.get(stateCode); } private static String mysqlToSql99(int errno) { - Integer err = new Integer(errno); + Integer err = Integer.valueOf(errno); if (mysqlToSql99State.containsKey(err)) { - return (String) mysqlToSql99State.get(err); + return mysqlToSql99State.get(err); } - return "HY000"; + return SQL_STATE_CLI_SPECIFIC_CONDITION; } /** @@ -861,10 +903,10 @@ } private static String mysqlToXOpen(int errno) { - Integer err = new Integer(errno); + Integer err = Integer.valueOf(errno); if (mysqlToSqlState.containsKey(err)) { - return (String) mysqlToSqlState.get(err); + return mysqlToSqlState.get(err); } return SQL_STATE_GENERAL_ERROR; @@ -882,67 +924,437 @@ */ public static SQLException createSQLException(String message, - String sqlState) { - if (sqlState != null) { - if (sqlState.startsWith("08")) { - return new MySQLNonTransientConnectionException(message, - sqlState); + String sqlState, ExceptionInterceptor interceptor) { + return createSQLException(message, sqlState, 0, interceptor); + } + + public static SQLException createSQLException(String message, ExceptionInterceptor interceptor) { + return createSQLException(message, interceptor, null); + } + public static SQLException createSQLException(String message, ExceptionInterceptor interceptor, Connection conn) { + SQLException sqlEx = new SQLException(message); + + if (interceptor != null) { + SQLException interceptedEx = interceptor.interceptException(sqlEx, conn); + + if (interceptedEx != null) { + return interceptedEx; } + } + + return sqlEx; + } - if (sqlState.startsWith("22")) { - return new MySQLDataException(message, sqlState); + public static SQLException createSQLException(String message, String sqlState, Throwable cause, ExceptionInterceptor interceptor) { + return createSQLException(message, sqlState, cause, interceptor, null); + } + public static SQLException createSQLException(String message, String sqlState, Throwable cause, ExceptionInterceptor interceptor, + Connection conn) { + if (THROWABLE_INIT_CAUSE_METHOD == null) { + if (cause != null) { + message = message + " due to " + cause.toString(); } + } + + SQLException sqlEx = createSQLException(message, sqlState, interceptor); + + if (cause != null && THROWABLE_INIT_CAUSE_METHOD != null) { + try { + THROWABLE_INIT_CAUSE_METHOD.invoke(sqlEx, new Object[] {cause}); + } catch (Throwable t) { + // we're not going to muck with that here, since it's + // an error condition anyway! + } + } + + if (interceptor != null) { + SQLException interceptedEx = interceptor.interceptException(sqlEx, conn); + + if (interceptedEx != null) { + return interceptedEx; + } + } + + return sqlEx; + } + + public static SQLException createSQLException(String message, + String sqlState, int vendorErrorCode, ExceptionInterceptor interceptor) { + return createSQLException(message, sqlState, vendorErrorCode, false, interceptor); + } + + /** + * + * @param message + * @param sqlState + * @param vendorErrorCode + * @param isTransient + * @param interceptor + * @return + */ + public static SQLException createSQLException(String message, + String sqlState, int vendorErrorCode, boolean isTransient, ExceptionInterceptor interceptor) { + return createSQLException(message, sqlState, vendorErrorCode, isTransient, interceptor, null); + } + public static SQLException createSQLException(String message, + String sqlState, int vendorErrorCode, boolean isTransient, ExceptionInterceptor interceptor, Connection conn) { + try { + SQLException sqlEx = null; + + if (sqlState != null) { + if (sqlState.startsWith("08")) { + if (isTransient) { + if (!Util.isJdbc4()) { + sqlEx = new MySQLTransientConnectionException( + message, sqlState, vendorErrorCode); + } else { + sqlEx = (SQLException) Util + .getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLTransientConnectionException", + new Class[] { String.class, + String.class, Integer.TYPE }, + new Object[] { message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else if (!Util.isJdbc4()) { + sqlEx = new MySQLNonTransientConnectionException( + message, sqlState, vendorErrorCode); + } else { + sqlEx = (SQLException) Util.getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException", + new Class[] { String.class, String.class, + Integer.TYPE }, new Object[] { + message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else if (sqlState.startsWith("22")) { + if (!Util.isJdbc4()) { + sqlEx = new MySQLDataException(message, sqlState, + vendorErrorCode); + } else { + sqlEx = (SQLException) Util + .getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLDataException", + new Class[] { String.class, String.class, + Integer.TYPE }, new Object[] { + message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else if (sqlState.startsWith("23")) { - if (sqlState.startsWith("23")) { - return new MySQLIntegrityConstraintViolationException(message, - sqlState); + if (!Util.isJdbc4()) { + sqlEx = new MySQLIntegrityConstraintViolationException( + message, sqlState, vendorErrorCode); + } else { + sqlEx = (SQLException) Util + .getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException", + new Class[] { String.class, String.class, + Integer.TYPE }, new Object[] { + message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else if (sqlState.startsWith("42")) { + if (!Util.isJdbc4()) { + sqlEx = new MySQLSyntaxErrorException(message, sqlState, + vendorErrorCode); + } else { + sqlEx = (SQLException) Util.getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException", + new Class[] { String.class, String.class, + Integer.TYPE }, new Object[] { + message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else if (sqlState.startsWith("40")) { + if (!Util.isJdbc4()) { + sqlEx = new MySQLTransactionRollbackException(message, + sqlState, vendorErrorCode); + } else { + sqlEx = (SQLException) Util + .getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException", + new Class[] { String.class, String.class, + Integer.TYPE }, new Object[] { + message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else if (sqlState.startsWith("70100")) { + if(!Util.isJdbc4()) { + sqlEx = new MySQLQueryInterruptedException(message, sqlState, vendorErrorCode); + } else { + sqlEx = (SQLException) Util.getInstance( + "com.mysql.jdbc.exceptions.jdbc4.MySQLQueryInterruptedException", + new Class[] { String.class, String.class, + Integer.TYPE }, new Object[] { + message, sqlState, + Integer.valueOf(vendorErrorCode) }, interceptor); + } + } else { + sqlEx = new SQLException(message, sqlState, vendorErrorCode); + } + } else { + sqlEx = new SQLException(message, sqlState, vendorErrorCode); } + + if (interceptor != null) { + SQLException interceptedEx = interceptor.interceptException(sqlEx, conn); + + if (interceptedEx != null) { + return interceptedEx; + } + } + + return sqlEx; + } catch (SQLException sqlEx) { + SQLException unexpectedEx = new SQLException( + "Unable to create correct SQLException class instance, error class/codes may be incorrect. Reason: " + + Util.stackTraceToString(sqlEx), + SQL_STATE_GENERAL_ERROR); + + if (interceptor != null) { + SQLException interceptedEx = interceptor.interceptException(unexpectedEx, conn); + + if (interceptedEx != null) { + return interceptedEx; + } + } + + return unexpectedEx; + } + } + + public static SQLException createCommunicationsException(MySQLConnection conn, long lastPacketSentTimeMs, + long lastPacketReceivedTimeMs, + Exception underlyingException, ExceptionInterceptor interceptor) { + SQLException exToReturn = null; + + if (!Util.isJdbc4()) { + exToReturn = new CommunicationsException(conn, lastPacketSentTimeMs, lastPacketReceivedTimeMs, underlyingException); + } else { + + try { + exToReturn = (SQLException) Util.handleNewInstance(JDBC_4_COMMUNICATIONS_EXCEPTION_CTOR, new Object[] { + conn, Long.valueOf(lastPacketSentTimeMs), Long.valueOf(lastPacketReceivedTimeMs), underlyingException}, interceptor); + } catch (SQLException sqlEx) { + // We should _never_ get this, but let's not swallow it either + + return sqlEx; + } + } + + if (THROWABLE_INIT_CAUSE_METHOD != null && underlyingException != null) { + try { + THROWABLE_INIT_CAUSE_METHOD.invoke(exToReturn, new Object[] {underlyingException}); + } catch (Throwable t) { + // we're not going to muck with that here, since it's + // an error condition anyway! + } + } + + if (interceptor != null) { + SQLException interceptedEx = interceptor.interceptException(exToReturn, conn); + + if (interceptedEx != null) { + return interceptedEx; + } + } + + return exToReturn; + } + + /** + * Creates a communications link failure message to be used + * in CommunicationsException that (hopefully) has some better + * information and suggestions based on heuristics. + * + * @param conn + * @param lastPacketSentTimeMs + * @param underlyingException + * @param streamingResultSetInPlay + * @return + */ + public static String createLinkFailureMessageBasedOnHeuristics( + MySQLConnection conn, + long lastPacketSentTimeMs, + long lastPacketReceivedTimeMs, + Exception underlyingException, + boolean streamingResultSetInPlay) { + long serverTimeoutSeconds = 0; + boolean isInteractiveClient = false; - if (sqlState.startsWith("42")) { - return new MySQLSyntaxErrorException(message, sqlState); + if (conn != null) { + isInteractiveClient = conn.getInteractiveClient(); + + String serverTimeoutSecondsStr = null; + + if (isInteractiveClient) { + serverTimeoutSecondsStr = conn + .getServerVariable("interactive_timeout"); //$NON-NLS-1$ + } else { + serverTimeoutSecondsStr = conn + .getServerVariable("wait_timeout"); //$NON-NLS-1$ } - if (sqlState.startsWith("40")) { - return new MySQLTransactionRollbackException(message, sqlState); + if (serverTimeoutSecondsStr != null) { + try { + serverTimeoutSeconds = Long + .parseLong(serverTimeoutSecondsStr); + } catch (NumberFormatException nfe) { + serverTimeoutSeconds = 0; + } } } - return new SQLException(message, sqlState); - } + StringBuffer exceptionMessageBuf = new StringBuffer(); + + long nowMs = System.currentTimeMillis(); + + if (lastPacketSentTimeMs == 0) { + lastPacketSentTimeMs = nowMs; + } - public static SQLException createSQLException(String message) { - return new SQLException(message); - } + long timeSinceLastPacketSentMs = (nowMs - lastPacketSentTimeMs); + long timeSinceLastPacketSeconds = timeSinceLastPacketSentMs / 1000; + + long timeSinceLastPacketReceivedMs = (nowMs - lastPacketReceivedTimeMs); + + int dueToTimeout = DUE_TO_TIMEOUT_FALSE; - public static SQLException createSQLException(String message, - String sqlState, int vendorErrorCode) { - if (sqlState != null) { - if (sqlState.startsWith("08")) { - return new MySQLNonTransientConnectionException(message, - sqlState, vendorErrorCode); - } + StringBuffer timeoutMessageBuf = null; - if (sqlState.startsWith("22")) { - return new MySQLDataException(message, sqlState, - vendorErrorCode); + if (streamingResultSetInPlay) { + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.ClientWasStreaming")); //$NON-NLS-1$ + } else { + if (serverTimeoutSeconds != 0) { + if (timeSinceLastPacketSeconds > serverTimeoutSeconds) { + dueToTimeout = DUE_TO_TIMEOUT_TRUE; + + timeoutMessageBuf = new StringBuffer(); + + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.2")); //$NON-NLS-1$ + + if (!isInteractiveClient) { + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.3")); //$NON-NLS-1$ + } else { + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.4")); //$NON-NLS-1$ + } + + } + } else if (timeSinceLastPacketSeconds > DEFAULT_WAIT_TIMEOUT_SECONDS) { + dueToTimeout = DUE_TO_TIMEOUT_MAYBE; + + timeoutMessageBuf = new StringBuffer(); + + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.5")); //$NON-NLS-1$ + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.6")); //$NON-NLS-1$ + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.7")); //$NON-NLS-1$ + timeoutMessageBuf.append(Messages + .getString("CommunicationsException.8")); //$NON-NLS-1$ } - if (sqlState.startsWith("23")) { - return new MySQLIntegrityConstraintViolationException(message, - sqlState, vendorErrorCode); + if (dueToTimeout == DUE_TO_TIMEOUT_TRUE + || dueToTimeout == DUE_TO_TIMEOUT_MAYBE) { + + if (lastPacketReceivedTimeMs != 0) { + Object[] timingInfo = { + Long.valueOf(timeSinceLastPacketReceivedMs), + Long.valueOf(timeSinceLastPacketSentMs) + }; + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.ServerPacketTimingInfo", //$NON-NLS-1$ + timingInfo)); + } else { + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.ServerPacketTimingInfoNoRecv", //$NON-NLS-1$ + new Object[] { Long.valueOf(timeSinceLastPacketSentMs)})); + } + + if (timeoutMessageBuf != null) { + exceptionMessageBuf.append(timeoutMessageBuf); + } + + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.11")); //$NON-NLS-1$ + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.12")); //$NON-NLS-1$ + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.13")); //$NON-NLS-1$ + + } else { + // + // Attempt to determine the reason for the underlying exception + // (we can only make a best-guess here) + // + + if (underlyingException instanceof BindException) { + if (conn.getLocalSocketAddress() != null + && !Util.interfaceExists(conn + .getLocalSocketAddress())) { + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.LocalSocketAddressNotAvailable")); //$NON-NLS-1$ + } else { + // too many client connections??? + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.TooManyClientConnections")); //$NON-NLS-1$ + } + } } + } - if (sqlState.startsWith("42")) { - return new MySQLSyntaxErrorException(message, sqlState, - vendorErrorCode); + if (exceptionMessageBuf.length() == 0) { + // We haven't figured out a good reason, so copy it. + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.20")); //$NON-NLS-1$ + + if (THROWABLE_INIT_CAUSE_METHOD == null && + underlyingException != null) { + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.21")); //$NON-NLS-1$ + exceptionMessageBuf.append(Util + .stackTraceToString(underlyingException)); } - if (sqlState.startsWith("40")) { - return new MySQLTransactionRollbackException(message, sqlState, - vendorErrorCode); + if (conn != null && conn.getMaintainTimeStats() + && !conn.getParanoid()) { + exceptionMessageBuf.append("\n\n"); //$NON-NLS-1$ + if (lastPacketReceivedTimeMs != 0) { + Object[] timingInfo = { + Long.valueOf(timeSinceLastPacketReceivedMs), + Long.valueOf(timeSinceLastPacketSentMs) + }; + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.ServerPacketTimingInfo", //$NON-NLS-1$ + timingInfo)); + } else { + exceptionMessageBuf.append(Messages + .getString("CommunicationsException.ServerPacketTimingInfoNoRecv", //$NON-NLS-1$ + new Object[] {Long.valueOf(timeSinceLastPacketSentMs)})); + } } } + + return exceptionMessageBuf.toString(); + } + + public static SQLException notImplemented() { + if (Util.isJdbc4()) { + try { + return (SQLException) Class.forName( + "java.sql.SQLFeatureNotSupportedException") + .newInstance(); + } catch (Throwable t) { + // proceed + } + } - return new SQLException(message, sqlState, vendorErrorCode); + return new NotImplemented(); } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Security.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Security.java (.../Security.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Security.java (.../Security.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,29 +1,29 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; +import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -34,7 +34,7 @@ * * @version $Id$ */ -class Security { +public class Security { private static final char PVERSION41_CHAR = '*'; private static final int SHA1_HASH_SIZE = 20; @@ -231,17 +231,18 @@ * IN Data for encryption * @param to * OUT Encrypt data to the buffer (may be the same) - * @param password - * IN Password used for encryption (same length) + * @param scramble + * IN Scramble used for encryption * @param length * IN Length of data to encrypt */ - static void passwordCrypt(byte[] from, byte[] to, byte[] password, + public static void xorString(byte[] from, byte[] to, byte[] scramble, int length) { int pos = 0; + int scrambleLength = scramble.length; - while ((pos < from.length) && (pos < length)) { - to[pos] = (byte) (from[pos] ^ password[pos]); + while (pos < length) { + to[pos] = (byte) (from[pos] ^ scramble[pos % scrambleLength]); pos++; } } @@ -274,7 +275,7 @@ cleansedPassword.append(c); } - return md.digest(cleansedPassword.toString().getBytes()); + return md.digest(StringUtils.getBytes(cleansedPassword.toString())); } /** @@ -319,17 +320,20 @@ // hash_stage1=xor(reply, sha1(public_seed,hash_stage2)) // candidate_hash2=sha1(hash_stage1) // check(candidate_hash2==hash_stage2) - static byte[] scramble411(String password, String seed) - throws NoSuchAlgorithmException { + public static byte[] scramble411(String password, String seed, String passwordEncoding) + throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest md = MessageDigest.getInstance("SHA-1"); //$NON-NLS-1$ - - byte[] passwordHashStage1 = md.digest(password.getBytes()); + + byte[] passwordHashStage1 = md + .digest((passwordEncoding == null || passwordEncoding.length() == 0) ? + StringUtils.getBytes(password) + : StringUtils.getBytes(password, passwordEncoding)); md.reset(); byte[] passwordHashStage2 = md.digest(passwordHashStage1); md.reset(); - byte[] seedAsBytes = seed.getBytes(); // for debugging + byte[] seedAsBytes = StringUtils.getBytes(seed, "ASCII"); // for debugging md.update(seedAsBytes); md.update(passwordHashStage2); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/SequentialBalanceStrategy.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/SequentialBalanceStrategy.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/SequentialBalanceStrategy.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,168 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * A balancing strategy that starts at a random point, and then advances + * in the list (wrapping around) for each new pickConnection() call. + * + * The initial point selection, and subsequent point selections are + * blacklist-aware. + * + */ +public class SequentialBalanceStrategy implements BalanceStrategy { + private int currentHostIndex = -1; + + public SequentialBalanceStrategy() { + } + + public void destroy() { + // we don't have anything to clean up + } + + public void init(Connection conn, Properties props) throws SQLException { + // we don't have anything to initialize + } + + public ConnectionImpl pickConnection(LoadBalancingConnectionProxy proxy, + List configuredHosts, Map liveConnections, long[] responseTimes, + int numRetries) throws SQLException { + int numHosts = configuredHosts.size(); + + SQLException ex = null; + + Map blackList = proxy.getGlobalBlacklist(); + + for (int attempts = 0; attempts < numRetries;) { + if (numHosts == 1) { + currentHostIndex = 0; // pathological case + } else if (currentHostIndex == -1) { + int random = (int) Math.floor((Math.random() * numHosts)); + + for (int i = random; i < numHosts; i++) { + if (!blackList.containsKey(configuredHosts.get(i))) { + currentHostIndex = i; + break; + } + } + + if (currentHostIndex == -1) { + for (int i = 0; i < random; i++) { + if (!blackList.containsKey(configuredHosts.get(i))) { + currentHostIndex = i; + break; + } + } + } + + if (currentHostIndex == -1) { + blackList = proxy.getGlobalBlacklist(); // it may have changed + // and the proxy returns a copy + + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + + continue; // retry + } + } else { + + + int i = currentHostIndex + 1; + boolean foundGoodHost = false; + + for (; i < numHosts; i++) { + if (!blackList.containsKey(configuredHosts.get(i))) { + currentHostIndex = i; + foundGoodHost = true; + break; + } + } + + if (!foundGoodHost) { + for (i = 0; i < currentHostIndex; i++) { + if (!blackList.containsKey(configuredHosts.get(i))) { + currentHostIndex = i; + foundGoodHost = true; + break; + } + } + } + + if (!foundGoodHost) { + blackList = proxy.getGlobalBlacklist(); // it may have changed + // and the proxy returns a copy + + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + + continue; // retry + } + } + + String hostPortSpec = configuredHosts.get(currentHostIndex); + + ConnectionImpl conn = liveConnections.get(hostPortSpec); + + if (conn == null) { + try { + conn = proxy.createConnectionForHost(hostPortSpec); + } catch (SQLException sqlEx) { + ex = sqlEx; + + if (sqlEx instanceof CommunicationsException + || "08S01".equals(sqlEx.getSQLState())) { + + proxy.addToGlobalBlacklist( hostPortSpec ); + + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + + continue; + } + throw sqlEx; + } + } + + return conn; + } + + if (ex != null) { + throw ex; + } + + return null; // we won't get here, compiler can't tell + } + +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/ServerPreparedStatement.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/ServerPreparedStatement.java (.../ServerPreparedStatement.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/ServerPreparedStatement.java (.../ServerPreparedStatement.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,62 +1,57 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import com.mysql.jdbc.PreparedStatement.BatchParams; -import com.mysql.jdbc.Statement.CancelTask; -import com.mysql.jdbc.exceptions.MySQLTimeoutException; -import com.mysql.jdbc.profiler.ProfileEventSink; -import com.mysql.jdbc.profiler.ProfilerEvent; - -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; - +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; - import java.net.URL; - import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.ParameterMetaData; import java.sql.Ref; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; - import java.util.ArrayList; -import java.util.BitSet; import java.util.Calendar; -import java.util.Locale; +import java.util.GregorianCalendar; import java.util.TimeZone; +import com.mysql.jdbc.exceptions.MySQLStatementCancelledException; +import com.mysql.jdbc.exceptions.MySQLTimeoutException; +import com.mysql.jdbc.log.LogUtils; +import com.mysql.jdbc.profiler.ProfilerEvent; + /** * JDBC Interface for MySQL-4.1 and newer server-side PreparedStatements. * @@ -65,10 +60,31 @@ * mmatthews Exp $ */ public class ServerPreparedStatement extends PreparedStatement { + private static final Constructor JDBC_4_SPS_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_SPS_CTOR = Class.forName("com.mysql.jdbc.JDBC4ServerPreparedStatement") + .getConstructor( + new Class[] { MySQLConnection.class, String.class, String.class, + Integer.TYPE, Integer.TYPE}); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_SPS_CTOR = null; + } + } + protected static final int BLOB_STREAM_READ_BUF_SIZE = 8192; - static class BatchedBindValues { - BindValue[] batchedParameterValues; + public static class BatchedBindValues { + public BindValue[] batchedParameterValues; BatchedBindValues(BindValue[] paramVals) { int numParams = paramVals.length; @@ -81,34 +97,28 @@ } } - static class BindValue { + public static class BindValue { - long boundBeforeExecutionNum = 0; + public long boundBeforeExecutionNum = 0; - long bindLength; /* Default length of data */ + public long bindLength; /* Default length of data */ - int bufferType; /* buffer type */ + public int bufferType; /* buffer type */ - byte byteBinding; + public double doubleBinding; - double doubleBinding; + public float floatBinding; - float floatBinding; + public boolean isLongData; /* long data indicator */ - int intBinding; + public boolean isNull; /* NULL indicator */ - boolean isLongData; /* long data indicator */ + public boolean isSet = false; /* has this parameter been set? */ - boolean isNull; /* NULL indicator */ + public long longBinding; /* all integral values are stored here */ - boolean isSet = false; /* has this parameter been set? */ + public Object value; /* The value to store */ - long longBinding; - - short shortBinding; - - Object value; /* The value to store */ - BindValue() { } @@ -119,9 +129,6 @@ this.isNull = copyMe.isNull; this.bufferType = copyMe.bufferType; this.bindLength = copyMe.bindLength; - this.byteBinding = copyMe.byteBinding; - this.shortBinding = copyMe.shortBinding; - this.intBinding = copyMe.intBinding; this.longBinding = copyMe.longBinding; this.floatBinding = copyMe.floatBinding; this.doubleBinding = copyMe.doubleBinding; @@ -132,9 +139,6 @@ this.value = null; this.isLongData = false; - this.byteBinding = 0; - this.shortBinding = 0; - this.intBinding = 0; this.longBinding = 0L; this.floatBinding = 0; this.doubleBinding = 0D; @@ -151,11 +155,8 @@ switch (this.bufferType) { case MysqlDefs.FIELD_TYPE_TINY: - return String.valueOf(byteBinding); case MysqlDefs.FIELD_TYPE_SHORT: - return String.valueOf(shortBinding); case MysqlDefs.FIELD_TYPE_LONG: - return String.valueOf(intBinding); case MysqlDefs.FIELD_TYPE_LONGLONG: return String.valueOf(longBinding); case MysqlDefs.FIELD_TYPE_FLOAT: @@ -171,20 +172,17 @@ case MysqlDefs.FIELD_TYPE_VARCHAR: if (quoteIfNeeded) { return "'" + String.valueOf(value) + "'"; - } else { - return String.valueOf(value); } + return String.valueOf(value); + default: if (value instanceof byte[]) { return "byte data"; - - } else { - if (quoteIfNeeded) { - return "'" + String.valueOf(value) + "'"; - } else { - return String.valueOf(value); - } } + if (quoteIfNeeded) { + return "'" + String.valueOf(value) + "'"; + } + return String.valueOf(value); } } @@ -225,29 +223,31 @@ case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: if (value instanceof byte[]) { return ((byte[]) value).length; - } else { - return ((String) value).length(); } + return ((String) value).length(); + default: return 0; } } } /* 1 (length) + 2 (year) + 1 (month) + 1 (day) */ - private static final byte MAX_DATE_REP_LENGTH = (byte) 5; + //private static final byte MAX_DATE_REP_LENGTH = (byte) 5; /* * 1 (length) + 2 (year) + 1 (month) + 1 (day) + 1 (hour) + 1 (minute) + 1 * (second) + 4 (microseconds) */ - private static final byte MAX_DATETIME_REP_LENGTH = 12; + //private static final byte MAX_DATETIME_REP_LENGTH = 12; /* * 1 (length) + 1 (is negative) + 4 (day count) + 1 (hour) + 1 (minute) + 1 * (seconds) + 4 (microseconds) */ - private static final byte MAX_TIME_REP_LENGTH = 13; + //private static final byte MAX_TIME_REP_LENGTH = 13; + + private boolean hasOnDuplicateKeyUpdate = false; private void storeTime(Buffer intoBuf, Time tm) throws SQLException { @@ -292,9 +292,6 @@ /** If this statement has been marked invalid, what was the reason? */ private SQLException invalidationException; - /** Does this query modify data? */ - private boolean isSelectQuery; - private Buffer outByteBuffer; /** Bind values for individual fields */ @@ -318,6 +315,42 @@ private boolean serverNeedsResetBeforeEachExecution; /** + * Creates a prepared statement instance -- We need to provide factory-style + * methods so we can support both JDBC3 (and older) and JDBC4 runtimes, + * otherwise the class verifier complains when it tries to load JDBC4-only + * interface classes that are present in JDBC4 method signatures. + */ + + protected static ServerPreparedStatement getInstance(MySQLConnection conn, + String sql, String catalog, int resultSetType, + int resultSetConcurrency) throws SQLException { + if (!Util.isJdbc4()) { + return new ServerPreparedStatement(conn, sql, catalog, + resultSetType, resultSetConcurrency); + } + + try { + return (ServerPreparedStatement) JDBC_4_SPS_CTOR.newInstance(new Object[] { conn, + sql, catalog, Integer.valueOf(resultSetType), + Integer.valueOf(resultSetConcurrency) }); + } catch (IllegalArgumentException e) { + throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR); + } catch (InstantiationException e) { + throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR); + } catch (IllegalAccessException e) { + throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR); + } catch (InvocationTargetException e) { + Throwable target = e.getTargetException(); + + if (target instanceof SQLException) { + throw (SQLException)target; + } + + throw new SQLException(target.toString(), SQLError.SQL_STATE_GENERAL_ERROR); + } + } + + /** * Creates a new ServerPreparedStatement object. * * @param conn @@ -330,16 +363,19 @@ * @throws SQLException * If an error occurs */ - public ServerPreparedStatement(Connection conn, String sql, String catalog, + protected ServerPreparedStatement(MySQLConnection conn, String sql, String catalog, int resultSetType, int resultSetConcurrency) throws SQLException { super(conn, catalog); checkNullOrEmptyQuery(sql); - this.isSelectQuery = StringUtils.startsWithIgnoreCaseAndWs(sql, - "SELECT"); //$NON-NLS-1$ + this.hasOnDuplicateKeyUpdate = containsOnDuplicateKeyInString(sql); + int startOfStatement = findStartOfStatement(sql); + + this.firstCharOfStmt = StringUtils.firstAlphaCharUc(sql, startOfStatement); + if (this.connection.versionMeetsMinimum(5, 0, 0)) { this.serverNeedsResetBeforeEachExecution = !this.connection.versionMeetsMinimum(5, 0, 3); @@ -348,11 +384,14 @@ !this.connection.versionMeetsMinimum(4, 1, 10); } + this.useAutoSlowLog = this.connection.getAutoSlowLog(); this.useTrueBoolean = this.connection.versionMeetsMinimum(3, 21, 23); - this.hasLimitClause = (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1); //$NON-NLS-1$ - this.firstCharOfStmt = StringUtils.firstNonWsCharUc(sql); - this.originalSql = sql; + + String statementComment = this.connection.getStatementComment(); + this.originalSql = (statementComment == null) ? sql : "/* " + + statementComment + " */ " + sql; + if (this.connection.versionMeetsMinimum(4, 1, 2)) { this.stringTypeCode = MysqlDefs.FIELD_TYPE_VAR_STRING; } else { @@ -368,12 +407,17 @@ } catch (Exception ex) { realClose(false, true); - throw SQLError.createSQLException(ex.toString(), - SQLError.SQL_STATE_GENERAL_ERROR); + SQLException sqlEx = SQLError.createSQLException(ex.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; } setResultSetType(resultSetType); setResultSetConcurrency(resultSetConcurrency); + + this.parameterTypes = new int[this.parameterCount]; } /** @@ -382,80 +426,80 @@ * @exception SQLException * if a database-access error occurs. * - * @see Statement#addBatch + * @see StatementImpl#addBatch */ - public synchronized void addBatch() throws SQLException { - checkClosed(); + public void addBatch() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { - if (this.batchedArgs == null) { - this.batchedArgs = new ArrayList(); + if (this.batchedArgs == null) { + this.batchedArgs = new ArrayList(); + } + + this.batchedArgs.add(new BatchedBindValues(this.parameterBindings)); } - - this.batchedArgs.add(new BatchedBindValues(this.parameterBindings)); } - protected String asSql(boolean quoteStreamsAndUnknowns) throws SQLException { + public String asSql(boolean quoteStreamsAndUnknowns) throws SQLException { - if (this.isClosed) { - return "statement has been closed, no further internal information available"; - } - - PreparedStatement pStmtForSub = null; - - try { - pStmtForSub = new PreparedStatement(this.connection, - this.originalSql, this.currentCatalog); - - int numParameters = pStmtForSub.parameterCount; - int ourNumParameters = this.parameterCount; - - for (int i = 0; (i < numParameters) && (i < ourNumParameters); i++) { - if (this.parameterBindings[i] != null) { - if (this.parameterBindings[i].isNull) { - pStmtForSub.setNull(i + 1, Types.NULL); - } else { - BindValue bindValue = this.parameterBindings[i]; - - // - // Handle primitives first - // - switch (bindValue.bufferType) { - - case MysqlDefs.FIELD_TYPE_TINY: - pStmtForSub.setByte(i + 1, bindValue.byteBinding); - break; - case MysqlDefs.FIELD_TYPE_SHORT: - pStmtForSub.setShort(i + 1, bindValue.shortBinding); - break; - case MysqlDefs.FIELD_TYPE_LONG: - pStmtForSub.setInt(i + 1, bindValue.intBinding); - break; - case MysqlDefs.FIELD_TYPE_LONGLONG: - pStmtForSub.setLong(i + 1, bindValue.longBinding); - break; - case MysqlDefs.FIELD_TYPE_FLOAT: - pStmtForSub.setFloat(i + 1, bindValue.floatBinding); - break; - case MysqlDefs.FIELD_TYPE_DOUBLE: - pStmtForSub.setDouble(i + 1, - bindValue.doubleBinding); - break; - default: - pStmtForSub.setObject(i + 1, - this.parameterBindings[i].value); - break; + synchronized (checkClosed().getConnectionMutex()) { + + PreparedStatement pStmtForSub = null; + + try { + pStmtForSub = PreparedStatement.getInstance(this.connection, + this.originalSql, this.currentCatalog); + + int numParameters = pStmtForSub.parameterCount; + int ourNumParameters = this.parameterCount; + + for (int i = 0; (i < numParameters) && (i < ourNumParameters); i++) { + if (this.parameterBindings[i] != null) { + if (this.parameterBindings[i].isNull) { + pStmtForSub.setNull(i + 1, Types.NULL); + } else { + BindValue bindValue = this.parameterBindings[i]; + + // + // Handle primitives first + // + switch (bindValue.bufferType) { + + case MysqlDefs.FIELD_TYPE_TINY: + pStmtForSub.setByte(i + 1, (byte)bindValue.longBinding); + break; + case MysqlDefs.FIELD_TYPE_SHORT: + pStmtForSub.setShort(i + 1, (short)bindValue.longBinding); + break; + case MysqlDefs.FIELD_TYPE_LONG: + pStmtForSub.setInt(i + 1, (int)bindValue.longBinding); + break; + case MysqlDefs.FIELD_TYPE_LONGLONG: + pStmtForSub.setLong(i + 1, bindValue.longBinding); + break; + case MysqlDefs.FIELD_TYPE_FLOAT: + pStmtForSub.setFloat(i + 1, bindValue.floatBinding); + break; + case MysqlDefs.FIELD_TYPE_DOUBLE: + pStmtForSub.setDouble(i + 1, + bindValue.doubleBinding); + break; + default: + pStmtForSub.setObject(i + 1, + this.parameterBindings[i].value); + break; + } } } } - } - - return pStmtForSub.asSql(quoteStreamsAndUnknowns); - } finally { - if (pStmtForSub != null) { - try { - pStmtForSub.close(); - } catch (SQLException sqlEx) { - ; // ignore + + return pStmtForSub.asSql(quoteStreamsAndUnknowns); + } finally { + if (pStmtForSub != null) { + try { + pStmtForSub.close(); + } catch (SQLException sqlEx) { + ; // ignore + } } } } @@ -466,20 +510,21 @@ * * @see com.mysql.jdbc.Statement#checkClosed() */ - protected void checkClosed() throws SQLException { + protected MySQLConnection checkClosed() throws SQLException { if (this.invalid) { throw this.invalidationException; } - super.checkClosed(); + return super.checkClosed(); } /** * @see java.sql.PreparedStatement#clearParameters() */ public void clearParameters() throws SQLException { - checkClosed(); - clearParametersInternal(true); + synchronized (checkClosed().getConnectionMutex()) { + clearParametersInternal(true); + } } private void clearParametersInternal(boolean clearServerParameters) @@ -506,107 +551,127 @@ protected boolean isCached = false; + private boolean useAutoSlowLog; + + private Calendar serverTzCalendar; + + private Calendar defaultTzCalendar; + protected void setClosed(boolean flag) { this.isClosed = flag; } + /** * @see java.sql.Statement#close() */ public void close() throws SQLException { - if (this.isCached) { - this.isClosed = true; - this.connection.recachePreparedStatement(this); - return; - } + MySQLConnection locallyScopedConn = this.connection; - realClose(true, true); - } + if (locallyScopedConn == null) return; // already closed - private void dumpCloseForTestcase() { - StringBuffer buf = new StringBuffer(); - this.connection.generateConnectionCommentBlock(buf); - buf.append("DEALLOCATE PREPARE debug_stmt_"); - buf.append(this.statementId); - buf.append(";\n"); + synchronized (locallyScopedConn.getConnectionMutex()) { - this.connection.dumpTestcaseQuery(buf.toString()); + if (this.isCached && !this.isClosed) { + clearParameters(); + + this.isClosed = true; + + this.connection.recachePreparedStatement(this); + return; + } + + realClose(true, true); + } } - private void dumpExecuteForTestcase() throws SQLException { - StringBuffer buf = new StringBuffer(); - - for (int i = 0; i < this.parameterCount; i++) { + private void dumpCloseForTestcase() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + StringBuffer buf = new StringBuffer(); this.connection.generateConnectionCommentBlock(buf); - - buf.append("SET @debug_stmt_param"); + buf.append("DEALLOCATE PREPARE debug_stmt_"); buf.append(this.statementId); - buf.append("_"); - buf.append(i); - buf.append("="); - - if (this.parameterBindings[i].isNull) { - buf.append("NULL"); - } else { - buf.append(this.parameterBindings[i].toString(true)); - } - buf.append(";\n"); + + this.connection.dumpTestcaseQuery(buf.toString()); } + } - this.connection.generateConnectionCommentBlock(buf); - - buf.append("EXECUTE debug_stmt_"); - buf.append(this.statementId); - - if (this.parameterCount > 0) { - buf.append(" USING "); + private void dumpExecuteForTestcase() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < this.parameterCount; i++) { - if (i > 0) { - buf.append(", "); - } - - buf.append("@debug_stmt_param"); + this.connection.generateConnectionCommentBlock(buf); + + buf.append("SET @debug_stmt_param"); buf.append(this.statementId); buf.append("_"); buf.append(i); - + buf.append("="); + + if (this.parameterBindings[i].isNull) { + buf.append("NULL"); + } else { + buf.append(this.parameterBindings[i].toString(true)); + } + + buf.append(";\n"); } + + this.connection.generateConnectionCommentBlock(buf); + + buf.append("EXECUTE debug_stmt_"); + buf.append(this.statementId); + + if (this.parameterCount > 0) { + buf.append(" USING "); + for (int i = 0; i < this.parameterCount; i++) { + if (i > 0) { + buf.append(", "); + } + + buf.append("@debug_stmt_param"); + buf.append(this.statementId); + buf.append("_"); + buf.append(i); + + } + } + + buf.append(";\n"); + + this.connection.dumpTestcaseQuery(buf.toString()); } - - buf.append(";\n"); - - this.connection.dumpTestcaseQuery(buf.toString()); } private void dumpPrepareForTestcase() throws SQLException { - - StringBuffer buf = new StringBuffer(this.originalSql.length() + 64); - - this.connection.generateConnectionCommentBlock(buf); - - buf.append("PREPARE debug_stmt_"); - buf.append(this.statementId); - buf.append(" FROM \""); - buf.append(this.originalSql); - buf.append("\";\n"); - - this.connection.dumpTestcaseQuery(buf.toString()); + synchronized (checkClosed().getConnectionMutex()) { + StringBuffer buf = new StringBuffer(this.originalSql.length() + 64); + + this.connection.generateConnectionCommentBlock(buf); + + buf.append("PREPARE debug_stmt_"); + buf.append(this.statementId); + buf.append(" FROM \""); + buf.append(this.originalSql); + buf.append("\";\n"); + + this.connection.dumpTestcaseQuery(buf.toString()); + } } - /** - * @see java.sql.Statement#executeBatch() - */ - public synchronized int[] executeBatchSerially() throws SQLException { - if (this.connection.isReadOnly()) { - throw SQLError.createSQLException(Messages - .getString("ServerPreparedStatement.2") //$NON-NLS-1$ - + Messages.getString("ServerPreparedStatement.3"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - checkClosed(); - - synchronized (this.connection.getMutex()) { + protected int[] executeBatchSerially(int batchTimeout) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + MySQLConnection locallyScopedConn = this.connection; + + + if (locallyScopedConn.isReadOnly()) { + throw SQLError.createSQLException(Messages + .getString("ServerPreparedStatement.2") //$NON-NLS-1$ + + Messages.getString("ServerPreparedStatement.3"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + clearWarnings(); // Store this for later, we're going to 'swap' them out @@ -621,7 +686,7 @@ updateCounts = new int[nbrCommands]; if (this.retrieveGeneratedKeys) { - this.batchedGeneratedKeys = new ArrayList(nbrCommands); + this.batchedGeneratedKeys = new ArrayList(nbrCommands); } for (int i = 0; i < nbrCommands; i++) { @@ -634,77 +699,100 @@ BindValue[] previousBindValuesForBatch = null; - for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { - Object arg = this.batchedArgs.get(commandIndex); - - if (arg instanceof String) { - updateCounts[commandIndex] = executeUpdate((String) arg); - } else { - this.parameterBindings = ((BatchedBindValues) arg).batchedParameterValues; - - try { - // We need to check types each time, as - // the user might have bound different - // types in each addBatch() - - if (previousBindValuesForBatch != null) { - for (int j = 0; j < this.parameterBindings.length; j++) { - if (this.parameterBindings[j].bufferType != previousBindValuesForBatch[j].bufferType) { - this.sendTypesToServer = true; - - break; + CancelTask timeoutTask = null; + + try { + if (locallyScopedConn.getEnableQueryTimeouts() && + batchTimeout != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + batchTimeout); + } + + for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { + Object arg = this.batchedArgs.get(commandIndex); + + if (arg instanceof String) { + updateCounts[commandIndex] = executeUpdate((String) arg); + } else { + this.parameterBindings = ((BatchedBindValues) arg).batchedParameterValues; + + try { + // We need to check types each time, as + // the user might have bound different + // types in each addBatch() + + if (previousBindValuesForBatch != null) { + for (int j = 0; j < this.parameterBindings.length; j++) { + if (this.parameterBindings[j].bufferType != previousBindValuesForBatch[j].bufferType) { + this.sendTypesToServer = true; + + break; + } } } - } - - try { - updateCounts[commandIndex] = executeUpdate(false, true); - } finally { - previousBindValuesForBatch = this.parameterBindings; - } - - if (this.retrieveGeneratedKeys) { - java.sql.ResultSet rs = null; - + try { - // we don't want to use our version, - // because we've altered the behavior of - // ours to support batch updates - // (catch-22) - // Ideally, what we need here is - // super.super.getGeneratedKeys() - // but that construct doesn't exist in - // Java, so that's why there's - // this kludge. - rs = getGeneratedKeysInternal(); - - while (rs.next()) { - this.batchedGeneratedKeys - .add(new byte[][] { rs - .getBytes(1) }); - } + updateCounts[commandIndex] = executeUpdate(false, true); } finally { - if (rs != null) { - rs.close(); + previousBindValuesForBatch = this.parameterBindings; + } + + if (this.retrieveGeneratedKeys) { + java.sql.ResultSet rs = null; + + try { + // we don't want to use our version, + // because we've altered the behavior of + // ours to support batch updates + // (catch-22) + // Ideally, what we need here is + // super.super.getGeneratedKeys() + // but that construct doesn't exist in + // Java, so that's why there's + // this kludge. + rs = getGeneratedKeysInternal(); + + while (rs.next()) { + this.batchedGeneratedKeys + .add(new ByteArrayRow(new byte[][] { rs + .getBytes(1) }, getExceptionInterceptor())); + } + } finally { + if (rs != null) { + rs.close(); + } } } + } catch (SQLException ex) { + updateCounts[commandIndex] = EXECUTE_FAILED; + + if (this.continueBatchOnError && + !(ex instanceof MySQLTimeoutException) && + !(ex instanceof MySQLStatementCancelledException) + && !hasDeadlockOrTimeoutRolledBackTx(ex)) { + sqlEx = ex; + } else { + int[] newUpdateCounts = new int[commandIndex]; + System.arraycopy(updateCounts, 0, + newUpdateCounts, 0, commandIndex); + + throw new java.sql.BatchUpdateException(ex + .getMessage(), ex.getSQLState(), ex + .getErrorCode(), newUpdateCounts); + } } - } catch (SQLException ex) { - updateCounts[commandIndex] = EXECUTE_FAILED; - - if (this.continueBatchOnError) { - sqlEx = ex; - } else { - int[] newUpdateCounts = new int[commandIndex]; - System.arraycopy(updateCounts, 0, - newUpdateCounts, 0, commandIndex); - - throw new java.sql.BatchUpdateException(ex - .getMessage(), ex.getSQLState(), ex - .getErrorCode(), newUpdateCounts); - } } } + } finally { + if (timeoutTask != null) { + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + } + + resetCancelledState(); } if (sqlEx != null) { @@ -728,57 +816,63 @@ * @see com.mysql.jdbc.PreparedStatement#executeInternal(int, * com.mysql.jdbc.Buffer, boolean, boolean) */ - protected com.mysql.jdbc.ResultSet executeInternal(int maxRowsToRetrieve, + protected com.mysql.jdbc.ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, - boolean queryIsSelectOnly, boolean unpackFields, Field[] metadataFromCache, + boolean queryIsSelectOnly, Field[] metadataFromCache, boolean isBatch) throws SQLException { - this.numberOfExecutions++; - - // We defer to server-side execution - try { - return serverExecute(maxRowsToRetrieve, createStreamingResultSet, - unpackFields, metadataFromCache); - } catch (SQLException sqlEx) { - // don't wrap SQLExceptions - if (this.connection.getEnablePacketDebug()) { - this.connection.getIO().dumpPacketRingBuffer(); + synchronized (checkClosed().getConnectionMutex()) { + this.numberOfExecutions++; + + // We defer to server-side execution + try { + return serverExecute(maxRowsToRetrieve, createStreamingResultSet, + metadataFromCache); + } catch (SQLException sqlEx) { + // don't wrap SQLExceptions + if (this.connection.getEnablePacketDebug()) { + this.connection.getIO().dumpPacketRingBuffer(); + } + + if (this.connection.getDumpQueriesOnException()) { + String extractedSql = toString(); + StringBuffer messageBuf = new StringBuffer(extractedSql + .length() + 32); + messageBuf + .append("\n\nQuery being executed when exception was thrown:\n"); + messageBuf.append(extractedSql); + messageBuf.append("\n\n"); + + sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf + .toString(), getExceptionInterceptor()); + } + + throw sqlEx; + } catch (Exception ex) { + if (this.connection.getEnablePacketDebug()) { + this.connection.getIO().dumpPacketRingBuffer(); + } + + SQLException sqlEx = SQLError.createSQLException(ex.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + + if (this.connection.getDumpQueriesOnException()) { + String extractedSql = toString(); + StringBuffer messageBuf = new StringBuffer(extractedSql + .length() + 32); + messageBuf + .append("\n\nQuery being executed when exception was thrown:\n"); + messageBuf.append(extractedSql); + messageBuf.append("\n\n"); + + sqlEx = ConnectionImpl.appendMessageToException(sqlEx, messageBuf + .toString(), getExceptionInterceptor()); + } + + sqlEx.initCause(ex); + + throw sqlEx; } - - if (this.connection.getDumpQueriesOnException()) { - String extractedSql = toString(); - StringBuffer messageBuf = new StringBuffer(extractedSql - .length() + 32); - messageBuf - .append("\n\nQuery being executed when exception was thrown:\n\n"); - messageBuf.append(extractedSql); - - sqlEx = Connection.appendMessageToException(sqlEx, messageBuf - .toString()); - } - - throw sqlEx; - } catch (Exception ex) { - if (this.connection.getEnablePacketDebug()) { - this.connection.getIO().dumpPacketRingBuffer(); - } - - SQLException sqlEx = SQLError.createSQLException(ex.toString(), - SQLError.SQL_STATE_GENERAL_ERROR); - - if (this.connection.getDumpQueriesOnException()) { - String extractedSql = toString(); - StringBuffer messageBuf = new StringBuffer(extractedSql - .length() + 32); - messageBuf - .append("\n\nQuery being executed when exception was thrown:\n\n"); - messageBuf.append(extractedSql); - - sqlEx = Connection.appendMessageToException(sqlEx, messageBuf - .toString()); - } - - throw sqlEx; } } @@ -808,104 +902,119 @@ * @return * @throws SQLException */ - private BindValue getBinding(int parameterIndex, boolean forLongData) + protected BindValue getBinding(int parameterIndex, boolean forLongData) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (this.parameterBindings.length == 0) { - throw SQLError.createSQLException(Messages - .getString("ServerPreparedStatement.8"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - parameterIndex--; - - if ((parameterIndex < 0) - || (parameterIndex >= this.parameterBindings.length)) { - throw SQLError.createSQLException(Messages - .getString("ServerPreparedStatement.9") //$NON-NLS-1$ - + (parameterIndex + 1) - + Messages.getString("ServerPreparedStatement.10") //$NON-NLS-1$ - + this.parameterBindings.length, - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - } - - if (this.parameterBindings[parameterIndex] == null) { - this.parameterBindings[parameterIndex] = new BindValue(); - } else { - if (this.parameterBindings[parameterIndex].isLongData - && !forLongData) { - this.detectedLongParameterSwitch = true; + if (this.parameterBindings.length == 0) { + throw SQLError.createSQLException(Messages + .getString("ServerPreparedStatement.8"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } + + parameterIndex--; + + if ((parameterIndex < 0) + || (parameterIndex >= this.parameterBindings.length)) { + throw SQLError.createSQLException(Messages + .getString("ServerPreparedStatement.9") //$NON-NLS-1$ + + (parameterIndex + 1) + + Messages.getString("ServerPreparedStatement.10") //$NON-NLS-1$ + + this.parameterBindings.length, + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (this.parameterBindings[parameterIndex] == null) { + this.parameterBindings[parameterIndex] = new BindValue(); + } else { + if (this.parameterBindings[parameterIndex].isLongData + && !forLongData) { + this.detectedLongParameterSwitch = true; + } + } + + this.parameterBindings[parameterIndex].isSet = true; + this.parameterBindings[parameterIndex].boundBeforeExecutionNum = this.numberOfExecutions; + + return this.parameterBindings[parameterIndex]; } + } - this.parameterBindings[parameterIndex].isSet = true; - this.parameterBindings[parameterIndex].boundBeforeExecutionNum = this.numberOfExecutions; - - return this.parameterBindings[parameterIndex]; + /** + * Return current bind values for use by Statement Interceptors. + * @return the bind values as set by setXXX and stored by addBatch + * @see #executeBatch() + * @see #addBatch() + */ + public BindValue[] getParameterBindValues() { + return parameterBindings; } /** * @see com.mysql.jdbc.PreparedStatement#getBytes(int) */ byte[] getBytes(int parameterIndex) throws SQLException { - BindValue bindValue = getBinding(parameterIndex, false); - - if (bindValue.isNull) { - return null; - } else if (bindValue.isLongData) { - throw new NotImplemented(); - } else { - if (this.outByteBuffer == null) { - this.outByteBuffer = new Buffer(this.connection - .getNetBufferLength()); + synchronized (checkClosed().getConnectionMutex()) { + BindValue bindValue = getBinding(parameterIndex, false); + + if (bindValue.isNull) { + return null; + } else if (bindValue.isLongData) { + throw SQLError.notImplemented(); + } else { + if (this.outByteBuffer == null) { + this.outByteBuffer = new Buffer(this.connection + .getNetBufferLength()); + } + + this.outByteBuffer.clear(); + + int originalPosition = this.outByteBuffer.getPosition(); + + storeBinding(this.outByteBuffer, bindValue, this.connection.getIO()); + + int newPosition = this.outByteBuffer.getPosition(); + + int length = newPosition - originalPosition; + + byte[] valueAsBytes = new byte[length]; + + System.arraycopy(this.outByteBuffer.getByteBuffer(), + originalPosition, valueAsBytes, 0, length); + + return valueAsBytes; } - - this.outByteBuffer.clear(); - - int originalPosition = this.outByteBuffer.getPosition(); - - storeBinding(this.outByteBuffer, bindValue, this.connection.getIO()); - - int newPosition = this.outByteBuffer.getPosition(); - - int length = newPosition - originalPosition; - - byte[] valueAsBytes = new byte[length]; - - System.arraycopy(this.outByteBuffer.getByteBuffer(), - originalPosition, valueAsBytes, 0, length); - - return valueAsBytes; } } /** * @see java.sql.PreparedStatement#getMetaData() */ public java.sql.ResultSetMetaData getMetaData() throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (this.resultFields == null) { - return null; + if (resultFields == null) { + return null; + } + + return new ResultSetMetaData(resultFields, connection.getUseOldAliasMetadataBehavior(), + connection.getYearIsDateType(), getExceptionInterceptor()); } - - return new ResultSetMetaData(this.resultFields, - this.connection.getUseOldAliasMetadataBehavior()); } /** * @see java.sql.PreparedStatement#getParameterMetaData() */ public ParameterMetaData getParameterMetaData() throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (this.parameterMetaData == null) { - this.parameterMetaData = new MysqlParameterMetadata( - this.parameterFields, this.parameterCount); + if (this.parameterMetaData == null) { + this.parameterMetaData = new MysqlParameterMetadata( + this.parameterFields, this.parameterCount, getExceptionInterceptor()); + } + + return this.parameterMetaData; } - - return this.parameterMetaData; } /** @@ -927,16 +1036,16 @@ */ protected void realClose(boolean calledExplicitly, boolean closeOpenResults) throws SQLException { - if (this.isClosed) { - return; - } + MySQLConnection locallyScopedConn = this.connection; - if (this.connection != null) { - if (this.connection.getAutoGenerateTestcaseScript()) { - dumpCloseForTestcase(); - } - - synchronized (this.connection.getMutex()) { + if (locallyScopedConn == null) return; // already closed + + synchronized (locallyScopedConn.getConnectionMutex()) { + + if (this.connection != null) { + if (this.connection.getAutoGenerateTestcaseScript()) { + dumpCloseForTestcase(); + } // // Don't communicate with the server if we're being @@ -948,36 +1057,39 @@ // called with). Well-behaved programs won't rely on finalizers // to clean up their statements. // - + SQLException exceptionDuringClose = null; - - - if (calledExplicitly) { - try { - - MysqlIO mysql = this.connection.getIO(); - - Buffer packet = mysql.getSharedSendPacket(); - - packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT); - packet.writeLong(this.serverStatementId); - - mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null, - packet, true, null); - } catch (SQLException sqlEx) { - exceptionDuringClose = sqlEx; + + if (calledExplicitly && !this.connection.isClosed()) { + synchronized (this.connection.getConnectionMutex()) { + try { + + MysqlIO mysql = this.connection.getIO(); + + Buffer packet = mysql.getSharedSendPacket(); + + packet.writeByte((byte) MysqlDefs.COM_CLOSE_STATEMENT); + packet.writeLong(this.serverStatementId); + + mysql.sendCommand(MysqlDefs.COM_CLOSE_STATEMENT, null, + packet, true, null, 0); + } catch (SQLException sqlEx) { + exceptionDuringClose = sqlEx; + } } - } - + + if (this.isCached) { + this.connection.decachePreparedStatement(this); + } super.realClose(calledExplicitly, closeOpenResults); - + clearParametersInternal(false); this.parameterBindings = null; - + this.parameterFields = null; this.resultFields = null; - + if (exceptionDuringClose != null) { throw exceptionDuringClose; } @@ -993,42 +1105,55 @@ * if an error occurs. */ protected void rePrepare() throws SQLException { - this.invalidationException = null; + synchronized (checkClosed().getConnectionMutex()) { + this.invalidationException = null; + + try { + serverPrepare(this.originalSql); + } catch (SQLException sqlEx) { + // don't wrap SQLExceptions + this.invalidationException = sqlEx; + } catch (Exception ex) { + this.invalidationException = SQLError.createSQLException(ex.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + this.invalidationException.initCause(ex); + } + + if (this.invalidationException != null) { + this.invalid = true; + + this.parameterBindings = null; + + this.parameterFields = null; + this.resultFields = null; + + if (this.results != null) { + try { + this.results.close(); + } catch (Exception ex) { + ; + } + } - try { - serverPrepare(this.originalSql); - } catch (SQLException sqlEx) { - // don't wrap SQLExceptions - this.invalidationException = sqlEx; - } catch (Exception ex) { - this.invalidationException = SQLError.createSQLException(ex.toString(), - SQLError.SQL_STATE_GENERAL_ERROR); - } + if (this.generatedKeysResults != null) { + try { + this.generatedKeysResults.close(); + } catch (Exception ex) { + ; + } + } - if (this.invalidationException != null) { - this.invalid = true; - - this.parameterBindings = null; - - this.parameterFields = null; - this.resultFields = null; - - if (this.results != null) { try { - this.results.close(); - } catch (Exception ex) { + closeAllOpenResults(); + } catch (Exception e) { ; } - } - - if (this.connection != null) { - if (this.maxRowsChanged) { - this.connection.unsetMaxRows(this); + + if (this.connection != null) { + if (!this.connection.getDontTrackOpenResources()) { + this.connection.unregisterStatement(this); + } } - - if (!this.connection.getDontTrackOpenResources()) { - this.connection.unregisterStatement(this); - } } } } @@ -1066,10 +1191,21 @@ * * @throws SQLException */ - private com.mysql.jdbc.ResultSet serverExecute(int maxRowsToRetrieve, - boolean createStreamingResultSet, boolean unpackFields, + private com.mysql.jdbc.ResultSetInternalMethods serverExecute(int maxRowsToRetrieve, + boolean createStreamingResultSet, Field[] metadataFromCache) throws SQLException { - synchronized (this.connection.getMutex()) { + synchronized (checkClosed().getConnectionMutex()) { + MysqlIO mysql = this.connection.getIO(); + + if (mysql.shouldIntercept()) { + ResultSetInternalMethods interceptedResults = + mysql.invokeStatementInterceptorsPre(this.originalSql, this, true); + + if (interceptedResults != null) { + return interceptedResults; + } + } + if (this.detectedLongParameterSwitch) { // Check when values were bound boolean firstFound = false; @@ -1082,11 +1218,10 @@ throw SQLError.createSQLException(Messages .getString("ServerPreparedStatement.11") //$NON-NLS-1$ + Messages.getString("ServerPreparedStatement.12"), //$NON-NLS-1$ - SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); - } else { - firstFound = true; - boundTimeToCheck = this.parameterBindings[i].boundBeforeExecutionNum; + SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); } + firstFound = true; + boundTimeToCheck = this.parameterBindings[i].boundBeforeExecutionNum; } } @@ -1103,7 +1238,7 @@ throw SQLError.createSQLException(Messages .getString("ServerPreparedStatement.13") + (i + 1) //$NON-NLS-1$ + Messages.getString("ServerPreparedStatement.14"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ } } @@ -1123,15 +1258,14 @@ // // store the parameter values // - MysqlIO mysql = this.connection.getIO(); Buffer packet = mysql.getSharedSendPacket(); packet.clear(); packet.writeByte((byte) MysqlDefs.COM_EXECUTE); packet.writeLong(this.serverStatementId); - boolean usingCursor = false; +// boolean usingCursor = false; if (this.connection.versionMeetsMinimum(4, 1, 2)) { // we only create cursor-backed result sets if @@ -1146,7 +1280,7 @@ && getResultSetConcurrency() == ResultSet.CONCUR_READ_ONLY && getFetchSize() > 0) { packet.writeByte(MysqlDefs.OPEN_CURSOR_FLAG); - usingCursor = true; +// usingCursor = true; } else { packet.writeByte((byte) 0); // placeholder for flags } @@ -1214,23 +1348,23 @@ begin = mysql.getCurrentTimeNanosOrMillis(); } - synchronized (this.cancelTimeoutMutex) { - this.wasCancelled = false; - } + resetCancelledState(); CancelTask timeoutTask = null; try { if (this.connection.getEnableQueryTimeouts() && this.timeoutInMillis != 0 && this.connection.versionMeetsMinimum(5, 0, 0)) { - timeoutTask = new CancelTask(); + timeoutTask = new CancelTask(this); this.connection.getCancelTimer().schedule(timeoutTask, this.timeoutInMillis); } + statementBegins(); + Buffer resultPacket = mysql.sendCommand(MysqlDefs.COM_EXECUTE, - null, packet, false, null); + null, packet, false, null, 0); long queryEndTime = 0L; @@ -1241,6 +1375,8 @@ if (timeoutTask != null) { timeoutTask.cancel(); + this.connection.getCancelTimer().purge(); + if (timeoutTask.caughtWhileCancelling != null) { throw timeoutTask.caughtWhileCancelling; } @@ -1250,8 +1386,17 @@ synchronized (this.cancelTimeoutMutex) { if (this.wasCancelled) { - this.wasCancelled = false; - throw new MySQLTimeoutException(); + SQLException cause = null; + + if (this.wasCancelledByTimeout) { + cause = new MySQLTimeoutException(); + } else { + cause = new MySQLStatementCancelledException(); + } + + resetCancelledState(); + + throw cause; } } @@ -1260,9 +1405,17 @@ if (logSlowQueries || gatherPerformanceMetrics) { long elapsedTime = queryEndTime - begin; - if (logSlowQueries - && (elapsedTime >= mysql.getSlowQueryThreshold())) { - queryWasSlow = true; + if (logSlowQueries) { + if (this.useAutoSlowLog) { + queryWasSlow = elapsedTime > this.connection.getSlowQueryThresholdMillis(); + } else { + queryWasSlow = this.connection.isAbonormallyLongQuery(elapsedTime); + + this.connection.reportQueryTime(elapsedTime); + } + } + + if (queryWasSlow) { StringBuffer mesgBuf = new StringBuffer( 48 + this.originalSql.length()); @@ -1287,7 +1440,7 @@ getId(), 0, System.currentTimeMillis(), elapsedTime, mysql .getQueryTimingUnits(), null, - new Throwable(), mesgBuf.toString())); + LogUtils.findCallingClassAndMethod(new Throwable()), mesgBuf.toString())); } if (gatherPerformanceMetrics) { @@ -1298,41 +1451,50 @@ this.connection.incrementNumberOfPreparedExecutes(); if (this.profileSQL) { - this.eventSink = ProfileEventSink + this.eventSink = ProfilerEventHandlerFactory .getInstance(this.connection); this.eventSink.consumeEvent(new ProfilerEvent( ProfilerEvent.TYPE_EXECUTE, "", this.currentCatalog, //$NON-NLS-1$ this.connectionId, this.statementId, -1, System - .currentTimeMillis(), (int) (mysql - .getCurrentTimeNanosOrMillis() - begin), - mysql.getQueryTimingUnits(), null, new Throwable(), + .currentTimeMillis(), mysql + .getCurrentTimeNanosOrMillis() - begin, + mysql.getQueryTimingUnits(), null, LogUtils.findCallingClassAndMethod(new Throwable()), truncateQueryToLog(asSql(true)))); } - com.mysql.jdbc.ResultSet rs = mysql.readAllResults(this, + com.mysql.jdbc.ResultSetInternalMethods rs = mysql.readAllResults(this, maxRowsToRetrieve, this.resultSetType, this.resultSetConcurrency, createStreamingResultSet, this.currentCatalog, resultPacket, true, this.fieldCount, - unpackFields, metadataFromCache); + metadataFromCache); + if (mysql.shouldIntercept()) { + ResultSetInternalMethods interceptedResults = + mysql.invokeStatementInterceptorsPost(this.originalSql, this, rs, true, null); + + if (interceptedResults != null) { + rs = interceptedResults; + } + } + if (this.profileSQL) { long fetchEndTime = mysql.getCurrentTimeNanosOrMillis(); this.eventSink.consumeEvent(new ProfilerEvent( ProfilerEvent.TYPE_FETCH, "", this.currentCatalog, this.connection.getId(), //$NON-NLS-1$ - getId(), rs.resultId, System.currentTimeMillis(), + getId(), 0 /* FIXME rs.resultId */, System.currentTimeMillis(), (fetchEndTime - queryEndTime), mysql .getQueryTimingUnits(), null, - new Throwable(), null)); + LogUtils.findCallingClassAndMethod(new Throwable()), null)); } if (queryWasSlow && this.connection.getExplainSlowQueries()) { String queryAsString = asSql(true); - mysql.explainSlowQuery(queryAsString.getBytes(), + mysql.explainSlowQuery(StringUtils.getBytes(queryAsString), queryAsString); } @@ -1350,9 +1512,18 @@ } return rs; + } catch (SQLException sqlEx) { + if (mysql.shouldIntercept()) { + mysql.invokeStatementInterceptorsPost(this.originalSql, this, null, true, sqlEx); + } + + throw sqlEx; } finally { + this.statementExecuting.set(false); + if (timeoutTask != null) { timeoutTask.cancel(); + this.connection.getCancelTimer().purge(); } } } @@ -1387,7 +1558,7 @@ */ private void serverLongData(int parameterIndex, BindValue longData) throws SQLException { - synchronized (this.connection.getMutex()) { + synchronized (checkClosed().getConnectionMutex()) { MysqlIO mysql = this.connection.getIO(); Buffer packet = mysql.getSharedSendPacket(); @@ -1403,7 +1574,7 @@ packet.writeBytesNoNull((byte[]) longData.value); mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, - null); + null, 0); } else if (value instanceof InputStream) { storeStream(mysql, parameterIndex, packet, (InputStream) value); } else if (value instanceof java.sql.Blob) { @@ -1415,13 +1586,13 @@ throw SQLError.createSQLException(Messages .getString("ServerPreparedStatement.18") //$NON-NLS-1$ + value.getClass().getName() + "'", //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } } private void serverPrepare(String sql) throws SQLException { - synchronized (this.connection.getMutex()) { + synchronized (checkClosed().getConnectionMutex()) { MysqlIO mysql = this.connection.getIO(); if (this.connection.getAutoGenerateTestcaseScript()) { @@ -1438,7 +1609,7 @@ } if (this.connection.getProfileSql()) { - begin = mysql.getCurrentTimeNanosOrMillis(); + begin = System.currentTimeMillis(); } String characterEncoding = null; @@ -1451,7 +1622,7 @@ Buffer prepareResultPacket = mysql.sendCommand( MysqlDefs.COM_PREPARE, sql, null, false, - characterEncoding); + characterEncoding, 0); if (this.connection.versionMeetsMinimum(4, 1, 1)) { // 4.1.1 and newer use the first byte @@ -1484,7 +1655,7 @@ System.currentTimeMillis(), mysql.getCurrentTimeNanosOrMillis() - begin, mysql.getQueryTimingUnits(), null, - new Throwable(), truncateQueryToLog(sql))); + LogUtils.findCallingClassAndMethod(new Throwable()), truncateQueryToLog(sql))); } if (this.parameterCount > 0) { @@ -1528,8 +1699,8 @@ .append("\n\nQuery being prepared when exception was thrown:\n\n"); messageBuf.append(this.originalSql); - sqlEx = Connection.appendMessageToException(sqlEx, - messageBuf.toString()); + sqlEx = ConnectionImpl.appendMessageToException(sqlEx, + messageBuf.toString(), getExceptionInterceptor()); } throw sqlEx; @@ -1542,25 +1713,27 @@ } } - private String truncateQueryToLog(String sql) { - String query = null; - - if (sql.length() > this.connection.getMaxQuerySizeToLog()) { - StringBuffer queryBuf = new StringBuffer( - this.connection.getMaxQuerySizeToLog() + 12); - queryBuf.append(sql.substring(0, this.connection.getMaxQuerySizeToLog())); - queryBuf.append(Messages.getString("MysqlIO.25")); + private String truncateQueryToLog(String sql) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + String query = null; - query = queryBuf.toString(); - } else { - query = sql; + if (sql.length() > this.connection.getMaxQuerySizeToLog()) { + StringBuffer queryBuf = new StringBuffer( + this.connection.getMaxQuerySizeToLog() + 12); + queryBuf.append(sql.substring(0, this.connection.getMaxQuerySizeToLog())); + queryBuf.append(Messages.getString("MysqlIO.25")); + + query = queryBuf.toString(); + } else { + query = sql; + } + + return query; } - - return query; } private void serverResetStatement() throws SQLException { - synchronized (this.connection.getMutex()) { + synchronized (checkClosed().getConnectionMutex()) { MysqlIO mysql = this.connection.getIO(); @@ -1572,12 +1745,15 @@ try { mysql.sendCommand(MysqlDefs.COM_RESET_STMT, null, packet, - !this.connection.versionMeetsMinimum(4, 1, 2), null); + !this.connection.versionMeetsMinimum(4, 1, 2), null, 0); } catch (SQLException sqlEx) { throw sqlEx; } catch (Exception ex) { - throw SQLError.createSQLException(ex.toString(), - SQLError.SQL_STATE_GENERAL_ERROR); + SQLException sqlEx = SQLError.createSQLException(ex.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ex); + + throw sqlEx; } finally { mysql.clearInputStream(); } @@ -1588,7 +1764,7 @@ * @see java.sql.PreparedStatement#setArray(int, java.sql.Array) */ public void setArray(int i, Array x) throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** @@ -1597,22 +1773,22 @@ */ public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - checkClosed(); - - if (x == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - BindValue binding = getBinding(parameterIndex, true); - setType(binding, MysqlDefs.FIELD_TYPE_BLOB); - - binding.value = x; - binding.isNull = false; - binding.isLongData = true; - - if (this.connection.getUseStreamLengthsInPrepStmts()) { - binding.bindLength = length; + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.BINARY); } else { - binding.bindLength = -1; + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = x; + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = length; + } else { + binding.bindLength = -1; + } } } } @@ -1622,24 +1798,25 @@ */ public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (x == null) { - setNull(parameterIndex, java.sql.Types.DECIMAL); - } else { - - BindValue binding = getBinding(parameterIndex, false); - - if (this.connection.versionMeetsMinimum(5, 0, 3)) { - setType(binding, MysqlDefs.FIELD_TYPE_NEW_DECIMAL); + if (x == null) { + setNull(parameterIndex, java.sql.Types.DECIMAL); } else { - setType(binding, this.stringTypeCode); + + BindValue binding = getBinding(parameterIndex, false); + + if (this.connection.versionMeetsMinimum(5, 0, 3)) { + setType(binding, MysqlDefs.FIELD_TYPE_NEW_DECIMAL); + } else { + setType(binding, this.stringTypeCode); + } + + binding.value = StringUtils + .fixDecimalExponent(StringUtils.consistentToString(x)); + binding.isNull = false; + binding.isLongData = false; } - - binding.value = StringUtils - .fixDecimalExponent(StringUtils.consistentToString(x)); - binding.isNull = false; - binding.isLongData = false; } } @@ -1649,22 +1826,23 @@ */ public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (x == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - BindValue binding = getBinding(parameterIndex, true); - setType(binding, MysqlDefs.FIELD_TYPE_BLOB); - - binding.value = x; - binding.isNull = false; - binding.isLongData = true; - - if (this.connection.getUseStreamLengthsInPrepStmts()) { - binding.bindLength = length; + if (x == null) { + setNull(parameterIndex, java.sql.Types.BINARY); } else { - binding.bindLength = -1; + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = x; + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = length; + } else { + binding.bindLength = -1; + } } } } @@ -1673,22 +1851,23 @@ * @see java.sql.PreparedStatement#setBlob(int, java.sql.Blob) */ public void setBlob(int parameterIndex, Blob x) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (x == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - BindValue binding = getBinding(parameterIndex, true); - setType(binding, MysqlDefs.FIELD_TYPE_BLOB); - - binding.value = x; - binding.isNull = false; - binding.isLongData = true; - - if (this.connection.getUseStreamLengthsInPrepStmts()) { - binding.bindLength = x.length(); + if (x == null) { + setNull(parameterIndex, java.sql.Types.BINARY); } else { - binding.bindLength = -1; + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = x; + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = x.length(); + } else { + binding.bindLength = -1; + } } } } @@ -1710,7 +1889,7 @@ setType(binding, MysqlDefs.FIELD_TYPE_TINY); binding.value = null; - binding.byteBinding = x; + binding.longBinding = x; binding.isNull = false; binding.isLongData = false; } @@ -1739,22 +1918,23 @@ */ public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (reader == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - BindValue binding = getBinding(parameterIndex, true); - setType(binding, MysqlDefs.FIELD_TYPE_BLOB); - - binding.value = reader; - binding.isNull = false; - binding.isLongData = true; - - if (this.connection.getUseStreamLengthsInPrepStmts()) { - binding.bindLength = length; + if (reader == null) { + setNull(parameterIndex, java.sql.Types.BINARY); } else { - binding.bindLength = -1; + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = reader; + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = length; + } else { + binding.bindLength = -1; + } } } } @@ -1763,22 +1943,23 @@ * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob) */ public void setClob(int parameterIndex, Clob x) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (x == null) { - setNull(parameterIndex, java.sql.Types.BINARY); - } else { - BindValue binding = getBinding(parameterIndex, true); - setType(binding, MysqlDefs.FIELD_TYPE_BLOB); - - binding.value = x.getCharacterStream(); - binding.isNull = false; - binding.isLongData = true; - - if (this.connection.getUseStreamLengthsInPrepStmts()) { - binding.bindLength = x.length(); + if (x == null) { + setNull(parameterIndex, java.sql.Types.BINARY); } else { - binding.bindLength = -1; + BindValue binding = getBinding(parameterIndex, true); + setType(binding, MysqlDefs.FIELD_TYPE_BLOB); + + binding.value = x.getCharacterStream(); + binding.isNull = false; + binding.isLongData = true; + + if (this.connection.getUseStreamLengthsInPrepStmts()) { + binding.bindLength = x.length(); + } else { + binding.bindLength = -1; + } } } } @@ -1831,24 +2012,25 @@ * @see java.sql.PreparedStatement#setDouble(int, double) */ public void setDouble(int parameterIndex, double x) throws SQLException { - checkClosed(); + synchronized (checkClosed().getConnectionMutex()) { - if (!this.connection.getAllowNanAndInf() - && (x == Double.POSITIVE_INFINITY - || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) { - throw SQLError.createSQLException("'" + x - + "' is not a valid numeric or approximate numeric value", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); - + if (!this.connection.getAllowNanAndInf() + && (x == Double.POSITIVE_INFINITY + || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) { + throw SQLError.createSQLException("'" + x + + "' is not a valid numeric or approximate numeric value", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + + } + + BindValue binding = getBinding(parameterIndex, false); + setType(binding, MysqlDefs.FIELD_TYPE_DOUBLE); + + binding.value = null; + binding.doubleBinding = x; + binding.isNull = false; + binding.isLongData = false; } - - BindValue binding = getBinding(parameterIndex, false); - setType(binding, MysqlDefs.FIELD_TYPE_DOUBLE); - - binding.value = null; - binding.doubleBinding = x; - binding.isNull = false; - binding.isLongData = false; } /** @@ -1876,7 +2058,7 @@ setType(binding, MysqlDefs.FIELD_TYPE_LONG); binding.value = null; - binding.intBinding = x; + binding.longBinding = x; binding.isNull = false; binding.isLongData = false; } @@ -1943,7 +2125,7 @@ * @see java.sql.PreparedStatement#setRef(int, java.sql.Ref) */ public void setRef(int i, Ref x) throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** @@ -1956,7 +2138,7 @@ setType(binding, MysqlDefs.FIELD_TYPE_SHORT); binding.value = null; - binding.shortBinding = x; + binding.longBinding = x; binding.isNull = false; binding.isLongData = false; } @@ -1993,7 +2175,9 @@ */ public void setTime(int parameterIndex, java.sql.Time x) throws SQLException { - setTimeInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false); + synchronized (checkClosed().getConnectionMutex()) { + setTimeInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false); + } } /** @@ -2031,28 +2215,32 @@ * @throws SQLException * if a database access error occurs */ - public void setTimeInternal(int parameterIndex, java.sql.Time x, + protected void setTimeInternal(int parameterIndex, java.sql.Time x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.TIME); - } else { - BindValue binding = getBinding(parameterIndex, false); - setType(binding, MysqlDefs.FIELD_TYPE_TIME); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.TIME); + } else { + BindValue binding = getBinding(parameterIndex, false); + setType(binding, MysqlDefs.FIELD_TYPE_TIME); + + if (!this.useLegacyDatetimeCode) { + binding.value = x; + } else { + Calendar sessionCalendar = getCalendarInstanceForSessionOrNew(); - Calendar sessionCalendar = getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar) { - binding.value = TimeUtil.changeTimezone(this.connection, - sessionCalendar, - targetCalendar, - x, tz, - this.connection.getServerTimezoneTZ(), - rollForward); + binding.value = TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + x, tz, + this.connection.getServerTimezoneTZ(), + rollForward); + } + + binding.isNull = false; + binding.isLongData = false; } - - binding.isNull = false; - binding.isLongData = false; } } @@ -2070,7 +2258,9 @@ */ public void setTimestamp(int parameterIndex, java.sql.Timestamp x) throws SQLException { - setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false); + synchronized (checkClosed().getConnectionMutex()) { + setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false); + } } /** @@ -2089,43 +2279,51 @@ */ public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException { - setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(), true); + synchronized (checkClosed().getConnectionMutex()) { + setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(), true); + } } protected void setTimestampInternal(int parameterIndex, java.sql.Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException { - if (x == null) { - setNull(parameterIndex, java.sql.Types.TIMESTAMP); - } else { - BindValue binding = getBinding(parameterIndex, false); - setType(binding, MysqlDefs.FIELD_TYPE_DATETIME); + synchronized (checkClosed().getConnectionMutex()) { + if (x == null) { + setNull(parameterIndex, java.sql.Types.TIMESTAMP); + } else { + BindValue binding = getBinding(parameterIndex, false); + setType(binding, MysqlDefs.FIELD_TYPE_DATETIME); + + if (!this.useLegacyDatetimeCode) { + binding.value = x; + } else { + Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? + this.connection.getUtcCalendar() : + getCalendarInstanceForSessionOrNew(); + + binding.value = TimeUtil.changeTimezone(this.connection, + sessionCalendar, + targetCalendar, + x, tz, + this.connection.getServerTimezoneTZ(), + rollForward); - Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? - this.connection.getUtcCalendar() : - getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar) { - binding.value = TimeUtil.changeTimezone(this.connection, - sessionCalendar, - targetCalendar, - x, tz, - this.connection.getServerTimezoneTZ(), - rollForward); + binding.isNull = false; + binding.isLongData = false; + } } - - binding.isNull = false; - binding.isLongData = false; } } - private void setType(BindValue oldValue, int bufferType) { - if (oldValue.bufferType != bufferType) { - this.sendTypesToServer = true; + protected void setType(BindValue oldValue, int bufferType) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (oldValue.bufferType != bufferType) { + this.sendTypesToServer = true; + } + + oldValue.bufferType = bufferType; } - - oldValue.bufferType = bufferType; } /** @@ -2151,7 +2349,7 @@ throws SQLException { checkClosed(); - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** @@ -2176,80 +2374,93 @@ */ private void storeBinding(Buffer packet, BindValue bindValue, MysqlIO mysql) throws SQLException { - try { - Object value = bindValue.value; - - // - // Handle primitives first - // - switch (bindValue.bufferType) { - - case MysqlDefs.FIELD_TYPE_TINY: - packet.writeByte(bindValue.byteBinding); - return; - case MysqlDefs.FIELD_TYPE_SHORT: - packet.ensureCapacity(2); - packet.writeInt(bindValue.shortBinding); - return; - case MysqlDefs.FIELD_TYPE_LONG: - packet.ensureCapacity(4); - packet.writeLong(bindValue.intBinding); - return; - case MysqlDefs.FIELD_TYPE_LONGLONG: - packet.ensureCapacity(8); - packet.writeLongLong(bindValue.longBinding); - return; - case MysqlDefs.FIELD_TYPE_FLOAT: - packet.ensureCapacity(4); - packet.writeFloat(bindValue.floatBinding); - return; - case MysqlDefs.FIELD_TYPE_DOUBLE: - packet.ensureCapacity(8); - packet.writeDouble(bindValue.doubleBinding); - return; - case MysqlDefs.FIELD_TYPE_TIME: - storeTime(packet, (Time) value); - return; - case MysqlDefs.FIELD_TYPE_DATE: - case MysqlDefs.FIELD_TYPE_DATETIME: - case MysqlDefs.FIELD_TYPE_TIMESTAMP: - storeDateTime(packet, (java.util.Date) value, mysql); - return; - case MysqlDefs.FIELD_TYPE_VAR_STRING: - case MysqlDefs.FIELD_TYPE_STRING: - case MysqlDefs.FIELD_TYPE_VARCHAR: - case MysqlDefs.FIELD_TYPE_DECIMAL: - case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: - if (value instanceof byte[]) { - packet.writeLenBytes((byte[]) value); - } else if (!this.isLoadDataQuery) { - packet.writeLenString((String) value, this.charEncoding, - this.connection.getServerCharacterEncoding(), - this.charConverter, this.connection - .parserKnowsUnicode(), - this.connection); - } else { - packet.writeLenBytes(((String) value).getBytes()); + synchronized (checkClosed().getConnectionMutex()) { + try { + Object value = bindValue.value; + + // + // Handle primitives first + // + switch (bindValue.bufferType) { + + case MysqlDefs.FIELD_TYPE_TINY: + packet.writeByte((byte)bindValue.longBinding); + return; + case MysqlDefs.FIELD_TYPE_SHORT: + packet.ensureCapacity(2); + packet.writeInt((int)bindValue.longBinding); + return; + case MysqlDefs.FIELD_TYPE_LONG: + packet.ensureCapacity(4); + packet.writeLong((int)bindValue.longBinding); + return; + case MysqlDefs.FIELD_TYPE_LONGLONG: + packet.ensureCapacity(8); + packet.writeLongLong(bindValue.longBinding); + return; + case MysqlDefs.FIELD_TYPE_FLOAT: + packet.ensureCapacity(4); + packet.writeFloat(bindValue.floatBinding); + return; + case MysqlDefs.FIELD_TYPE_DOUBLE: + packet.ensureCapacity(8); + packet.writeDouble(bindValue.doubleBinding); + return; + case MysqlDefs.FIELD_TYPE_TIME: + storeTime(packet, (Time) value); + return; + case MysqlDefs.FIELD_TYPE_DATE: + case MysqlDefs.FIELD_TYPE_DATETIME: + case MysqlDefs.FIELD_TYPE_TIMESTAMP: + storeDateTime(packet, (java.util.Date) value, mysql, bindValue.bufferType); + return; + case MysqlDefs.FIELD_TYPE_VAR_STRING: + case MysqlDefs.FIELD_TYPE_STRING: + case MysqlDefs.FIELD_TYPE_VARCHAR: + case MysqlDefs.FIELD_TYPE_DECIMAL: + case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: + if (value instanceof byte[]) { + packet.writeLenBytes((byte[]) value); + } else if (!this.isLoadDataQuery) { + packet.writeLenString((String) value, this.charEncoding, + this.connection.getServerCharacterEncoding(), + this.charConverter, this.connection + .parserKnowsUnicode(), + this.connection); + } else { + packet.writeLenBytes(StringUtils.getBytes((String) value)); + } + + return; } - - return; + + + } catch (UnsupportedEncodingException uEE) { + throw SQLError.createSQLException(Messages + .getString("ServerPreparedStatement.22") //$NON-NLS-1$ + + this.connection.getEncoding() + "'", //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); } - - - } catch (UnsupportedEncodingException uEE) { - throw SQLError.createSQLException(Messages - .getString("ServerPreparedStatement.22") //$NON-NLS-1$ - + this.connection.getEncoding() + "'", //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); } } - private void storeDataTime412AndOlder(Buffer intoBuf, java.util.Date dt) + private void storeDateTime412AndOlder(Buffer intoBuf, java.util.Date dt, int bufferType) throws SQLException { - - Calendar sessionCalendar = getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar) { + synchronized (checkClosed().getConnectionMutex()) { + Calendar sessionCalendar = null; + + if (!this.useLegacyDatetimeCode) { + if (bufferType == MysqlDefs.FIELD_TYPE_DATE) { + sessionCalendar = getDefaultTzCalendar(); + } else { + sessionCalendar = getServerTzCalendar(); + } + } else { + sessionCalendar = (dt instanceof Timestamp && + this.connection.getUseJDBCCompliantTimezoneShift()) ? + this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew(); + } + java.util.Date oldTime = sessionCalendar.getTime(); try { @@ -2284,25 +2495,45 @@ } } - private void storeDateTime(Buffer intoBuf, java.util.Date dt, MysqlIO mysql) + /** + * + * @param intoBuf + * @param dt + * @param mysql + * @param bufferType + * @throws SQLException + */ + private void storeDateTime(Buffer intoBuf, java.util.Date dt, MysqlIO mysql, int bufferType) throws SQLException { - if (this.connection.versionMeetsMinimum(4, 1, 3)) { - storeDateTime413AndNewer(intoBuf, dt); - } else { - storeDataTime412AndOlder(intoBuf, dt); + synchronized (checkClosed().getConnectionMutex()) { + if (this.connection.versionMeetsMinimum(4, 1, 3)) { + storeDateTime413AndNewer(intoBuf, dt, bufferType); + } else { + storeDateTime412AndOlder(intoBuf, dt, bufferType); + } } } - private void storeDateTime413AndNewer(Buffer intoBuf, java.util.Date dt) + private void storeDateTime413AndNewer(Buffer intoBuf, java.util.Date dt, int bufferType) throws SQLException { - Calendar sessionCalendar = (dt instanceof Timestamp && - this.connection.getUseJDBCCompliantTimezoneShift()) ? - this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew(); - - synchronized (sessionCalendar) { + synchronized (checkClosed().getConnectionMutex()) { + Calendar sessionCalendar = null; + + if (!this.useLegacyDatetimeCode) { + if (bufferType == MysqlDefs.FIELD_TYPE_DATE) { + sessionCalendar = getDefaultTzCalendar(); + } else { + sessionCalendar = getServerTzCalendar(); + } + } else { + sessionCalendar = (dt instanceof Timestamp && + this.connection.getUseJDBCCompliantTimezoneShift()) ? + this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew(); + } + + java.util.Date oldTime = sessionCalendar.getTime(); - - + try { sessionCalendar.setTime(dt); @@ -2344,7 +2575,7 @@ } if (length == 11) { - // MySQL expects microseconds, not nanos + // MySQL expects microseconds, not nanos intoBuf.writeLong(((java.sql.Timestamp) dt).getNanos() / 1000); } @@ -2354,163 +2585,193 @@ } } + private Calendar getServerTzCalendar() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (serverTzCalendar == null) { + serverTzCalendar = new GregorianCalendar(this.connection.getServerTimezoneTZ()); + } + + return this.serverTzCalendar; + } + } + + private Calendar getDefaultTzCalendar() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (defaultTzCalendar == null) { + defaultTzCalendar = new GregorianCalendar(TimeZone.getDefault()); + } + + return this.defaultTzCalendar; + } + } + // // TO DO: Investigate using NIO to do this faster // private void storeReader(MysqlIO mysql, int parameterIndex, Buffer packet, Reader inStream) throws SQLException { - String forcedEncoding = this.connection.getClobCharacterEncoding(); - - String clobEncoding = - (forcedEncoding == null ? this.connection.getEncoding() : forcedEncoding); - - int maxBytesChar = 2; + synchronized (checkClosed().getConnectionMutex()) { + String forcedEncoding = this.connection.getClobCharacterEncoding(); - if (clobEncoding != null) { - if (!clobEncoding.equals("UTF-16")) { - maxBytesChar = this.connection.getMaxBytesPerChar(clobEncoding); + String clobEncoding = + (forcedEncoding == null ? this.connection.getEncoding() : forcedEncoding); + + int maxBytesChar = 2; - if (maxBytesChar == 1) { - maxBytesChar = 2; // for safety + if (clobEncoding != null) { + if (!clobEncoding.equals("UTF-16")) { + maxBytesChar = this.connection.getMaxBytesPerChar(clobEncoding); + + if (maxBytesChar == 1) { + maxBytesChar = 2; // for safety + } + } else { + maxBytesChar = 4; } - } else { - maxBytesChar = 4; } - } + + char[] buf = new char[BLOB_STREAM_READ_BUF_SIZE / maxBytesChar]; - char[] buf = new char[BLOB_STREAM_READ_BUF_SIZE / maxBytesChar]; - - int numRead = 0; - - int bytesInPacket = 0; - int totalBytesRead = 0; - int bytesReadAtLastSend = 0; - int packetIsFullAt = this.connection.getBlobSendChunkSize(); - - - - try { - packet.clear(); - packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); - packet.writeLong(this.serverStatementId); - packet.writeInt((parameterIndex)); - - boolean readAny = false; + int numRead = 0; + + int bytesInPacket = 0; + int totalBytesRead = 0; + int bytesReadAtLastSend = 0; + int packetIsFullAt = this.connection.getBlobSendChunkSize(); - while ((numRead = inStream.read(buf)) != -1) { - readAny = true; - byte[] valueAsBytes = StringUtils.getBytes(buf, null, - clobEncoding, this.connection - .getServerCharacterEncoding(), 0, numRead, - this.connection.parserKnowsUnicode()); - - packet.writeBytesNoNull(valueAsBytes, 0, valueAsBytes.length); - - bytesInPacket += valueAsBytes.length; - totalBytesRead += valueAsBytes.length; - - if (bytesInPacket >= packetIsFullAt) { - bytesReadAtLastSend = totalBytesRead; - - mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, - true, null); - - bytesInPacket = 0; - packet.clear(); - packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); - packet.writeLong(this.serverStatementId); - packet.writeInt((parameterIndex)); - } - } - - if (totalBytesRead != bytesReadAtLastSend) { - mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, - null); - } - if (!readAny) { - mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, - null); - } - } catch (IOException ioEx) { - throw SQLError.createSQLException(Messages - .getString("ServerPreparedStatement.24") //$NON-NLS-1$ - + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR); - } finally { - if (this.connection.getAutoClosePStmtStreams()) { - if (inStream != null) { - try { - inStream.close(); - } catch (IOException ioEx) { - ; // ignore + try { + packet.clear(); + packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); + packet.writeLong(this.serverStatementId); + packet.writeInt((parameterIndex)); + + boolean readAny = false; + + while ((numRead = inStream.read(buf)) != -1) { + readAny = true; + + byte[] valueAsBytes = StringUtils.getBytes(buf, null, + clobEncoding, this.connection + .getServerCharacterEncoding(), 0, numRead, + this.connection.parserKnowsUnicode(), getExceptionInterceptor()); + + packet.writeBytesNoNull(valueAsBytes, 0, valueAsBytes.length); + + bytesInPacket += valueAsBytes.length; + totalBytesRead += valueAsBytes.length; + + if (bytesInPacket >= packetIsFullAt) { + bytesReadAtLastSend = totalBytesRead; + + mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, + true, null, 0); + + bytesInPacket = 0; + packet.clear(); + packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); + packet.writeLong(this.serverStatementId); + packet.writeInt((parameterIndex)); } } + + if (totalBytesRead != bytesReadAtLastSend) { + mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, + null, 0); + } + + if (!readAny) { + mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, + null, 0); + } + } catch (IOException ioEx) { + SQLException sqlEx = SQLError.createSQLException(Messages + .getString("ServerPreparedStatement.24") //$NON-NLS-1$ + + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ioEx); + + throw sqlEx; + } finally { + if (this.connection.getAutoClosePStmtStreams()) { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException ioEx) { + ; // ignore + } + } + } } } } private void storeStream(MysqlIO mysql, int parameterIndex, Buffer packet, InputStream inStream) throws SQLException { - byte[] buf = new byte[BLOB_STREAM_READ_BUF_SIZE]; - - int numRead = 0; - - try { - int bytesInPacket = 0; - int totalBytesRead = 0; - int bytesReadAtLastSend = 0; - int packetIsFullAt = this.connection.getBlobSendChunkSize(); - - packet.clear(); - packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); - packet.writeLong(this.serverStatementId); - packet.writeInt((parameterIndex)); - - boolean readAny = false; + synchronized (checkClosed().getConnectionMutex()) { + byte[] buf = new byte[BLOB_STREAM_READ_BUF_SIZE]; + + int numRead = 0; - while ((numRead = inStream.read(buf)) != -1) { - - readAny = true; + try { + int bytesInPacket = 0; + int totalBytesRead = 0; + int bytesReadAtLastSend = 0; + int packetIsFullAt = this.connection.getBlobSendChunkSize(); + + packet.clear(); + packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); + packet.writeLong(this.serverStatementId); + packet.writeInt((parameterIndex)); + + boolean readAny = false; - packet.writeBytesNoNull(buf, 0, numRead); - bytesInPacket += numRead; - totalBytesRead += numRead; - - if (bytesInPacket >= packetIsFullAt) { - bytesReadAtLastSend = totalBytesRead; - - mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, - true, null); - - bytesInPacket = 0; - packet.clear(); - packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); - packet.writeLong(this.serverStatementId); - packet.writeInt((parameterIndex)); + while ((numRead = inStream.read(buf)) != -1) { + + readAny = true; + + packet.writeBytesNoNull(buf, 0, numRead); + bytesInPacket += numRead; + totalBytesRead += numRead; + + if (bytesInPacket >= packetIsFullAt) { + bytesReadAtLastSend = totalBytesRead; + + mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, + true, null, 0); + + bytesInPacket = 0; + packet.clear(); + packet.writeByte((byte) MysqlDefs.COM_LONG_DATA); + packet.writeLong(this.serverStatementId); + packet.writeInt((parameterIndex)); + } } - } - - if (totalBytesRead != bytesReadAtLastSend) { - mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, - null); - } - - if (!readAny) { - mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, - null); - } - } catch (IOException ioEx) { - throw SQLError.createSQLException(Messages - .getString("ServerPreparedStatement.25") //$NON-NLS-1$ - + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR); - } finally { - if (this.connection.getAutoClosePStmtStreams()) { - if (inStream != null) { - try { - inStream.close(); - } catch (IOException ioEx) { - ; // ignore + + if (totalBytesRead != bytesReadAtLastSend) { + mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, + null, 0); + } + + if (!readAny) { + mysql.sendCommand(MysqlDefs.COM_LONG_DATA, null, packet, true, + null, 0); + } + } catch (IOException ioEx) { + SQLException sqlEx = SQLError.createSQLException(Messages + .getString("ServerPreparedStatement.25") //$NON-NLS-1$ + + ioEx.toString(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(ioEx); + + throw sqlEx; + } finally { + if (this.connection.getAutoClosePStmtStreams()) { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException ioEx) { + ; // ignore + } } } } @@ -2541,96 +2802,141 @@ return serverStatementId; } - public synchronized boolean canRewriteAsMultivalueInsertStatement() { - if (!super.canRewriteAsMultivalueInsertStatement()) { - return false; + private boolean hasCheckedRewrite = false; + private boolean canRewrite = false; + + public boolean canRewriteAsMultiValueInsertAtSqlLevel() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (!hasCheckedRewrite) { + this.hasCheckedRewrite = true; + this.canRewrite = canRewrite(this.originalSql, isOnDuplicateKeyUpdate(), getLocationOfOnDuplicateKeyUpdate(), 0); + // We need to client-side parse this to get the VALUES clause, etc. + this.parseInfo = new ParseInfo(this.originalSql, this.connection, this.connection.getMetaData(), this.charEncoding, this.charConverter); + } + + return this.canRewrite; } + } - BindValue[] currentBindValues = null; - BindValue[] previousBindValues = null; - - int nbrCommands = this.batchedArgs.size(); - - // Can't have type changes between sets of bindings for this to work... - - for (int commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { - Object arg = this.batchedArgs.get(commandIndex); - - if (!(arg instanceof String)) { - - currentBindValues = ((BatchedBindValues) arg).batchedParameterValues; - - // We need to check types each time, as - // the user might have bound different - // types in each addBatch() - - if (previousBindValues != null) { - for (int j = 0; j < this.parameterBindings.length; j++) { - if (currentBindValues[j].bufferType != previousBindValues[j].bufferType) { - return false; + + public boolean canRewriteAsMultivalueInsertStatement() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (!canRewriteAsMultiValueInsertAtSqlLevel()) { + return false; + } + + BindValue[] currentBindValues = null; + BindValue[] previousBindValues = null; + + int nbrCommands = this.batchedArgs.size(); + + // Can't have type changes between sets of bindings for this to work... + + for (int commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { + Object arg = this.batchedArgs.get(commandIndex); + + if (!(arg instanceof String)) { + + currentBindValues = ((BatchedBindValues) arg).batchedParameterValues; + + // We need to check types each time, as + // the user might have bound different + // types in each addBatch() + + if (previousBindValues != null) { + for (int j = 0; j < this.parameterBindings.length; j++) { + if (currentBindValues[j].bufferType != previousBindValues[j].bufferType) { + return false; + } } } } } + + + + return true; } - - return true; } + + private int locationOfOnDuplicateKeyUpdate = -2; + + protected int getLocationOfOnDuplicateKeyUpdate() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.locationOfOnDuplicateKeyUpdate == -2) { + this.locationOfOnDuplicateKeyUpdate = getOnDuplicateKeyLocation(this.originalSql); + } + + return this.locationOfOnDuplicateKeyUpdate; + } + } + + protected boolean isOnDuplicateKeyUpdate() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return getLocationOfOnDuplicateKeyUpdate() != -1; + } + } + + + /** * Computes the maximum parameter set size, and entire batch size given * the number of arguments in the batch. + * @throws SQLException */ - protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) { - long sizeOfEntireBatch = 1 + /* com_execute */ + 4 /* stmt id */ + 1 /* flags */ + 4 /* batch count padding */; - long maxSizeOfParameterSet = 0; - - for (int i = 0; i < numBatchedArgs; i++) { - BindValue[] paramArg = ((BatchedBindValues) this.batchedArgs.get(i)).batchedParameterValues; - - long sizeOfParameterSet = 0; + protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + long sizeOfEntireBatch = 1 + /* com_execute */ + 4 /* stmt id */ + 1 /* flags */ + 4 /* batch count padding */; + long maxSizeOfParameterSet = 0; - sizeOfParameterSet += (this.parameterCount + 7) / 8; // for isNull - - sizeOfParameterSet += this.parameterCount * 2; // have to send types - - for (int j = 0; j < this.parameterBindings.length; j++) { - if (!paramArg[j].isNull) { - - long size = paramArg[j].getBoundLength(); - - if (paramArg[j].isLongData) { - if (size != -1) { + for (int i = 0; i < numBatchedArgs; i++) { + BindValue[] paramArg = ((BatchedBindValues) this.batchedArgs.get(i)).batchedParameterValues; + + long sizeOfParameterSet = 0; + + sizeOfParameterSet += (this.parameterCount + 7) / 8; // for isNull + + sizeOfParameterSet += this.parameterCount * 2; // have to send types + + for (int j = 0; j < this.parameterBindings.length; j++) { + if (!paramArg[j].isNull) { + + long size = paramArg[j].getBoundLength(); + + if (paramArg[j].isLongData) { + if (size != -1) { + sizeOfParameterSet += size; + } + } else { sizeOfParameterSet += size; } - } else { - sizeOfParameterSet += size; } } - } + + sizeOfEntireBatch += sizeOfParameterSet; + + if (sizeOfParameterSet > maxSizeOfParameterSet) { + maxSizeOfParameterSet = sizeOfParameterSet; + } + } - sizeOfEntireBatch += sizeOfParameterSet; - - if (sizeOfParameterSet > maxSizeOfParameterSet) { - maxSizeOfParameterSet = sizeOfParameterSet; - } - } - - return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch}; + return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch}; + } } - + protected int setOneBatchedParameterSet( java.sql.PreparedStatement batchedStatement, int batchedParamIndex, Object paramSet) throws SQLException { BindValue[] paramArg = ((BatchedBindValues) paramSet).batchedParameterValues; - + for (int j = 0; j < paramArg.length; j++) { if (paramArg[j].isNull) { batchedStatement.setNull(batchedParamIndex++, Types.NULL); } else { if (paramArg[j].isLongData) { Object value = paramArg[j].value; - + if (value instanceof InputStream) { batchedStatement.setBinaryStream(batchedParamIndex++, (InputStream) value, @@ -2641,20 +2947,20 @@ (int) paramArg[j].bindLength); } } else { - + switch (paramArg[j].bufferType) { - + case MysqlDefs.FIELD_TYPE_TINY: batchedStatement.setByte(batchedParamIndex++, - paramArg[j].byteBinding); + (byte)paramArg[j].longBinding); break; case MysqlDefs.FIELD_TYPE_SHORT: batchedStatement.setShort(batchedParamIndex++, - paramArg[j].shortBinding); + (short)paramArg[j].longBinding); break; case MysqlDefs.FIELD_TYPE_LONG: batchedStatement.setInt(batchedParamIndex++, - paramArg[j].intBinding); + (int)paramArg[j].longBinding); break; case MysqlDefs.FIELD_TYPE_LONGLONG: batchedStatement.setLong(batchedParamIndex++, @@ -2687,26 +2993,27 @@ case MysqlDefs.FIELD_TYPE_DECIMAL: case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: Object value = paramArg[j].value; - + if (value instanceof byte[]) { batchedStatement.setBytes(batchedParamIndex, (byte[]) value); } else { batchedStatement.setString(batchedParamIndex, (String) value); } - - BindValue asBound = ((ServerPreparedStatement) batchedStatement) - .getBinding( - batchedParamIndex + 1 /* - * uses 1-based - * offset - */, - false); - asBound.bufferType = paramArg[j].bufferType; - + + // If we ended up here as a multi-statement, we're not working with a server prepared statement + + if (batchedStatement instanceof ServerPreparedStatement) { + BindValue asBound = ((ServerPreparedStatement) batchedStatement) + .getBinding( + batchedParamIndex, + false); + asBound.bufferType = paramArg[j].bufferType; + } + batchedParamIndex++; - + break; default: throw new IllegalArgumentException( @@ -2719,4 +3026,24 @@ return batchedParamIndex; } + + protected boolean containsOnDuplicateKeyUpdateInSQL() { + return this.hasOnDuplicateKeyUpdate; + } + + protected PreparedStatement prepareBatchedInsertSQL(MySQLConnection localConn, int numBatches) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + try { + PreparedStatement pstmt = new ServerPreparedStatement(localConn, this.parseInfo.getSqlForBatch(numBatches), this.currentCatalog, this.resultSetConcurrency, this.resultSetType); + pstmt.setRetrieveGeneratedKeys(this.retrieveGeneratedKeys); + + return pstmt; + } catch (UnsupportedEncodingException e) { + SQLException sqlEx = SQLError.createSQLException("Unable to prepare batch statement", SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); + sqlEx.initCause(e); + + throw sqlEx; + } + } + } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/SingleByteCharsetConverter.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/SingleByteCharsetConverter.java (.../SingleByteCharsetConverter.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/SingleByteCharsetConverter.java (.../SingleByteCharsetConverter.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,29 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.UnsupportedEncodingException; - import java.sql.SQLException; import java.util.HashMap; import java.util.Map; @@ -43,7 +41,7 @@ private static final int BYTE_RANGE = (1 + Byte.MAX_VALUE) - Byte.MIN_VALUE; private static byte[] allBytes = new byte[BYTE_RANGE]; - private static final Map CONVERTER_MAP = new HashMap(); + private static final Map CONVERTER_MAP = new HashMap(); private final static byte[] EMPTY_BYTE_ARRAY = new byte[0]; @@ -71,6 +69,7 @@ * * @param encodingName * the Java character encoding name + * @param conn * * @return a converter for the given encoding name * @throws UnsupportedEncodingException @@ -79,7 +78,7 @@ public static synchronized SingleByteCharsetConverter getInstance( String encodingName, Connection conn) throws UnsupportedEncodingException, SQLException { - SingleByteCharsetConverter instance = (SingleByteCharsetConverter) CONVERTER_MAP + SingleByteCharsetConverter instance = CONVERTER_MAP .get(encodingName); if (instance == null) { @@ -101,8 +100,14 @@ */ public static SingleByteCharsetConverter initCharset(String javaEncodingName) throws UnsupportedEncodingException, SQLException { - if (CharsetMapping.isMultibyteCharset(javaEncodingName)) { - return null; + try { + if (CharsetMapping.isMultibyteCharset(javaEncodingName)) { + return null; + } + } catch (RuntimeException ex) { + SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, null); + sqlEx.initCause(ex); + throw sqlEx; } SingleByteCharsetConverter converter = new SingleByteCharsetConverter( @@ -178,7 +183,27 @@ return bytes; } + + public final byte[] toBytesWrapped(char[] c, char beginWrap, char endWrap) { + if (c == null) { + return null; + } + int length = c.length + 2; + int charLength = c.length; + + byte[] bytes = new byte[length]; + bytes[0] = this.charToByteMap[beginWrap]; + + for (int i = 0; i < charLength; i++) { + bytes[i + 1] = this.charToByteMap[c[i]]; + } + + bytes[length - 1] = this.charToByteMap[endWrap]; + + return bytes; + } + public final byte[] toBytes(char[] chars, int offset, int length) { if (chars == null) { return null; @@ -218,7 +243,29 @@ return bytes; } + + public final byte[] toBytesWrapped(String s, char beginWrap, char endWrap) { + if (s == null) { + return null; + } + int stringLength = s.length(); + + int length = stringLength + 2; + + byte[] bytes = new byte[length]; + + bytes[0] = this.charToByteMap[beginWrap]; + + for (int i = 0; i < stringLength; i++) { + bytes[i + 1] = this.charToByteMap[s.charAt(i)]; + } + + bytes[length - 1] = this.charToByteMap[endWrap]; + + return bytes; + } + /** * Convert the given string to an array of bytes. * Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/SocketFactory.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/SocketFactory.java (.../SocketFactory.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/SocketFactory.java (.../SocketFactory.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,34 +1,31 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.IOException; - import java.net.Socket; import java.net.SocketException; - import java.util.Properties; /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/SocketMetadata.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/SocketMetadata.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/SocketMetadata.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,30 @@ +/* + Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; + +public interface SocketMetadata { + public boolean isLocallyConnected(ConnectionImpl conn) throws SQLException; +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StandardLoadBalanceExceptionChecker.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StandardLoadBalanceExceptionChecker.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StandardLoadBalanceExceptionChecker.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,122 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +public class StandardLoadBalanceExceptionChecker implements + LoadBalanceExceptionChecker { + + private List sqlStateList; + private List> sqlExClassList; + + public boolean shouldExceptionTriggerFailover(SQLException ex) { + String sqlState = ex.getSQLState(); + + if (sqlState != null) { + if (sqlState.startsWith("08")) { + // connection error + return true; + } + if(this.sqlStateList != null){ + // check against SQLState list + for(Iterator i = sqlStateList.iterator(); i.hasNext(); ){ + if(sqlState.startsWith(i.next().toString())){ + return true; + } + } + } + } + + // always handle CommunicationException + if(ex instanceof CommunicationsException){ + return true; + } + if(this.sqlExClassList != null){ + // check against configured class lists + for(Iterator> i = sqlExClassList.iterator(); i.hasNext(); ){ + if(i.next().isInstance(ex)){ + return true; + } + } + } + // no matches + return false; + + } + + public void destroy() { + // TODO Auto-generated method stub + + } + + public void init(Connection conn, Properties props) throws SQLException { + configureSQLStateList(props.getProperty("loadBalanceSQLStateFailover", null)); + configureSQLExceptionSubclassList(props.getProperty("loadBalanceSQLExceptionSubclassFailover", null)); + + } + + private void configureSQLStateList(String sqlStates){ + if(sqlStates == null || "".equals(sqlStates)){ + return; + } + List states = StringUtils.split(sqlStates, ",", true); + List newStates = new ArrayList(); + + for (String state : states){ + if(state.length() > 0){ + newStates.add(state); + } + } + if(newStates.size() > 0){ + this.sqlStateList = newStates; + } + + } + private void configureSQLExceptionSubclassList(String sqlExClasses){ + if(sqlExClasses == null || "".equals(sqlExClasses)){ + return; + } + List classes = StringUtils.split(sqlExClasses, ",", true); + List> newClasses = new ArrayList>(); + + for (String exClass : classes) { + try{ + Class c = Class.forName(exClass); + newClasses.add(c); + } catch (Exception e){ + // ignore and don't check, class doesn't exist + } + } + if(newClasses.size() > 0){ + this.sqlExClassList = newClasses; + } + + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StandardSocketFactory.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StandardSocketFactory.java (.../StandardSocketFactory.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StandardSocketFactory.java (.../StandardSocketFactory.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,47 +1,49 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.IOException; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; - import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.Socket; +import java.net.SocketAddress; import java.net.SocketException; - +import java.net.UnknownHostException; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Properties; /** * Socket factory for vanilla TCP/IP sockets (the standard) - * + * * @author Mark Matthews */ -public class StandardSocketFactory implements SocketFactory { +public class StandardSocketFactory implements SocketFactory, SocketMetadata { public static final String TCP_NO_DELAY_PROPERTY_NAME = "tcpNoDelay"; @@ -87,40 +89,54 @@ /** The underlying TCP/IP socket to use */ protected Socket rawSocket = null; + /** The remaining login time in milliseconds. Initial value set from defined DriverManager.setLoginTimeout() */ + protected int loginTimeoutCountdown = DriverManager.getLoginTimeout() * 1000; + + /** Time when last Login Timeout check occurred */ + protected long loginTimeoutCheckTimestamp = System.currentTimeMillis(); + + /** Backup original Socket timeout to be restored after handshake */ + protected int socketTimeoutBackup = 0; + /** * Called by the driver after issuing the MySQL protocol handshake and * reading the results of the handshake. - * + * * @throws SocketException * if a socket error occurs * @throws IOException * if an I/O error occurs - * + * * @return The socket to use after the handshake */ public Socket afterHandshake() throws SocketException, IOException { + resetLoginTimeCountdown(); + this.rawSocket.setSoTimeout(this.socketTimeoutBackup); return this.rawSocket; } /** * Called by the driver before issuing the MySQL protocol handshake. Should * return the socket instance that should be used during the handshake. - * + * * @throws SocketException * if a socket error occurs * @throws IOException * if an I/O error occurs - * + * * @return the socket to use before the handshake */ public Socket beforeHandshake() throws SocketException, IOException { + resetLoginTimeCountdown(); + this.socketTimeoutBackup = this.rawSocket.getSoTimeout(); + this.rawSocket.setSoTimeout(getRealTimeout(this.socketTimeoutBackup)); return this.rawSocket; } /** * Configures socket properties based on properties from the connection * (tcpNoDelay, snd/rcv buf, traffic class, etc). - * + * * @param props * @throws SocketException * @throws IOException @@ -160,7 +176,7 @@ if (trafficClass > 0 && setTraficClassMethod != null) { setTraficClassMethod.invoke(sock, - new Object[] { new Integer(trafficClass) }); + new Object[] { Integer.valueOf(trafficClass) }); } } catch (Throwable t) { unwrapExceptionToProperClassAndThrowIt(t); @@ -170,8 +186,7 @@ /** * @see com.mysql.jdbc.SocketFactory#createSocket(Properties) */ - public Socket connect(String hostname, int portNumber, Properties props) - throws SocketException, IOException { + public Socket connect(String hostname, int portNumber, Properties props) throws SocketException, IOException { if (props != null) { this.host = hostname; @@ -180,47 +195,38 @@ Method connectWithTimeoutMethod = null; Method socketBindMethod = null; - Class socketAddressClass = null; + Class socketAddressClass = null; - String localSocketHostname = props - .getProperty("localSocketAddress"); + String localSocketHostname = props.getProperty("localSocketAddress"); String connectTimeoutStr = props.getProperty("connectTimeout"); int connectTimeout = 0; - boolean wantsTimeout = (connectTimeoutStr != null - && connectTimeoutStr.length() > 0 && !connectTimeoutStr - .equals("0")); + boolean wantsTimeout = (connectTimeoutStr != null && connectTimeoutStr.length() > 0 && !connectTimeoutStr + .equals("0")) || this.loginTimeoutCountdown > 0; - boolean wantsLocalBind = (localSocketHostname != null && localSocketHostname - .length() > 0); + boolean wantsLocalBind = (localSocketHostname != null && localSocketHostname.length() > 0); boolean needsConfigurationBeforeConnect = socketNeedsConfigurationBeforeConnect(props); - - if (wantsTimeout || wantsLocalBind || needsConfigurationBeforeConnect) { + if (wantsTimeout || wantsLocalBind || needsConfigurationBeforeConnect) { if (connectTimeoutStr != null) { try { connectTimeout = Integer.parseInt(connectTimeoutStr); } catch (NumberFormatException nfe) { - throw new SocketException("Illegal value '" - + connectTimeoutStr + "' for connectTimeout"); + throw new SocketException("Illegal value '" + connectTimeoutStr + "' for connectTimeout"); } } try { - // Have to do this with reflection, otherwise older JVMs - // croak - socketAddressClass = Class - .forName("java.net.SocketAddress"); + // Have to do this with reflection, otherwise older JVMs croak + socketAddressClass = Class.forName("java.net.SocketAddress"); - connectWithTimeoutMethod = Socket.class.getMethod( - "connect", new Class[] { socketAddressClass, - Integer.TYPE }); + connectWithTimeoutMethod = Socket.class.getMethod("connect", new Class[] { socketAddressClass, + Integer.TYPE }); - socketBindMethod = Socket.class.getMethod("bind", - new Class[] { socketAddressClass }); + socketBindMethod = Socket.class.getMethod("bind", new Class[] { socketAddressClass }); } catch (NoClassDefFoundError noClassDefFound) { // ignore, we give a better error below if needed @@ -231,107 +237,87 @@ } if (wantsLocalBind && socketBindMethod == null) { - throw new SocketException( - "Can't specify \"localSocketAddress\" on JVMs older than 1.4"); + throw new SocketException("Can't specify \"localSocketAddress\" on JVMs older than 1.4"); } if (wantsTimeout && connectWithTimeoutMethod == null) { - throw new SocketException( - "Can't specify \"connectTimeout\" on JVMs older than 1.4"); + throw new SocketException("Can't specify \"connectTimeout\" on JVMs older than 1.4"); } } if (this.host != null) { if (!(wantsLocalBind || wantsTimeout || needsConfigurationBeforeConnect)) { - InetAddress[] possibleAddresses = InetAddress - .getAllByName(this.host); + InetAddress[] possibleAddresses = InetAddress.getAllByName(this.host); Throwable caughtWhileConnecting = null; - // Need to loop through all possible addresses, in case - // someone has IPV6 configured (SuSE, for example...) - + // Need to loop through all possible addresses, in case someone has IPV6 configured (SuSE, for + // example...) for (int i = 0; i < possibleAddresses.length; i++) { try { - this.rawSocket = new Socket(possibleAddresses[i], - port); + this.rawSocket = new Socket(possibleAddresses[i], this.port); configureSocket(this.rawSocket, props); break; } catch (Exception ex) { + resetLoginTimeCountdown(); caughtWhileConnecting = ex; } } - if (rawSocket == null) { + if (this.rawSocket == null) { unwrapExceptionToProperClassAndThrowIt(caughtWhileConnecting); } } else { - // must explicitly state this due to classloader issues - // when running on older JVMs :( + // must explicitly state this due to classloader issues when running on older JVMs :( try { + InetAddress[] possibleAddresses = InetAddress.getAllByName(this.host); - InetAddress[] possibleAddresses = InetAddress - .getAllByName(this.host); - Throwable caughtWhileConnecting = null; Object localSockAddr = null; - Class inetSocketAddressClass = null; + Class inetSocketAddressClass = null; - Constructor addrConstructor = null; + Constructor addrConstructor = null; try { - inetSocketAddressClass = Class - .forName("java.net.InetSocketAddress"); + inetSocketAddressClass = Class.forName("java.net.InetSocketAddress"); - addrConstructor = inetSocketAddressClass - .getConstructor(new Class[] { - InetAddress.class, Integer.TYPE }); + addrConstructor = inetSocketAddressClass.getConstructor(new Class[] { InetAddress.class, + Integer.TYPE }); if (wantsLocalBind) { - localSockAddr = addrConstructor - .newInstance(new Object[] { - InetAddress - .getByName(localSocketHostname), - new Integer(0 /* - * use ephemeral - * port - */) }); - + localSockAddr = addrConstructor.newInstance(new Object[] { + InetAddress.getByName(localSocketHostname), + new Integer(0 /* use ephemeral port */) }); } } catch (Throwable ex) { unwrapExceptionToProperClassAndThrowIt(ex); } - // Need to loop through all possible addresses, in case - // someone has IPV6 configured (SuSE, for example...) - + // Need to loop through all possible addresses, in case someone has IPV6 configured (SuSE, for + // example...) for (int i = 0; i < possibleAddresses.length; i++) { - try { this.rawSocket = new Socket(); configureSocket(this.rawSocket, props); - Object sockAddr = addrConstructor - .newInstance(new Object[] { - possibleAddresses[i], - new Integer(port) }); - // bind to the local port, null is 'ok', it - // means - // use the ephemeral port - socketBindMethod.invoke(rawSocket, - new Object[] { localSockAddr }); + Object sockAddr = addrConstructor.newInstance(new Object[] { possibleAddresses[i], + Integer.valueOf(this.port) }); + // bind to the local port if not using the ephemeral port + if (localSockAddr != null) { + socketBindMethod.invoke(this.rawSocket, new Object[] { localSockAddr }); + } - connectWithTimeoutMethod.invoke(rawSocket, - new Object[] { sockAddr, - new Integer(connectTimeout) }); + connectWithTimeoutMethod.invoke(this.rawSocket, + new Object[] { sockAddr, Integer.valueOf(getRealTimeout(connectTimeout)) }); break; } catch (Exception ex) { + resetLoginTimeCountdown(); this.rawSocket = null; caughtWhileConnecting = ex; @@ -346,6 +332,7 @@ unwrapExceptionToProperClassAndThrowIt(t); } } + resetLoginTimeCountdown(); return this.rawSocket; } @@ -357,7 +344,6 @@ /** * Does the configureSocket() need to be called before the socket is * connect()d based on the properties supplied? - * */ private boolean socketNeedsConfigurationBeforeConnect(Properties props) { int receiveBufferSize = Integer.parseInt(props.getProperty( @@ -406,4 +392,101 @@ throw new SocketException(caughtWhileConnecting.toString()); } -} + + public static final String IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME = "com.mysql.jdbc.test.isLocalHostnameReplacement"; + + public boolean isLocallyConnected(com.mysql.jdbc.ConnectionImpl conn) + throws SQLException { + long threadId = conn.getId(); + java.sql.Statement processListStmt = conn.getMetadataSafeStatement(); + ResultSet rs = null; + + try { + String processHost = null; + + rs = processListStmt.executeQuery("SHOW PROCESSLIST"); + + while (rs.next()) { + long id = rs.getLong(1); + + if (threadId == id) { + + processHost = rs.getString(3); + + break; + } + } + + // "inject" for tests + if (System.getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME) != null) { + processHost = System + .getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME); + } else if (conn.getProperties().getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME) != null) { + processHost = conn.getProperties().getProperty(IS_LOCAL_HOSTNAME_REPLACEMENT_PROPERTY_NAME); + } + + if (processHost != null) { + if (processHost.indexOf(":") != -1) { + processHost = processHost.split(":")[0]; + + try { + boolean isLocal = false; + + InetAddress whereMysqlThinksIConnectedFrom = InetAddress.getByName(processHost); + SocketAddress remoteSocketAddr = this.rawSocket.getRemoteSocketAddress(); + + if (remoteSocketAddr instanceof InetSocketAddress) { + InetAddress whereIConnectedTo = ((InetSocketAddress)remoteSocketAddr).getAddress(); + + isLocal = whereMysqlThinksIConnectedFrom.equals(whereIConnectedTo); + } + + return isLocal; + } catch (UnknownHostException e) { + conn.getLog().logWarn( + Messages.getString( + "Connection.CantDetectLocalConnect", + new Object[] { this.host }), e); + + return false; + } + } + } + + return false; + } finally { + processListStmt.close(); + } + } + + /** + * Decrements elapsed time since last reset from login timeout count down. + * + * @throws SocketException + * If the login timeout is reached or exceeded. + */ + protected void resetLoginTimeCountdown() throws SocketException { + if (this.loginTimeoutCountdown > 0) { + long now = System.currentTimeMillis(); + this.loginTimeoutCountdown -= now - this.loginTimeoutCheckTimestamp; + if (this.loginTimeoutCountdown <= 0) { + throw new SocketException(Messages.getString("Connection.LoginTimeout")); + } + this.loginTimeoutCheckTimestamp = now; + } + } + + /** + * Validates the connection/socket timeout that must really be used. + * + * @param expectedTimeout + * The timeout to validate. + * @return The timeout to be used. + */ + protected int getRealTimeout(int expectedTimeout) { + if (this.loginTimeoutCountdown > 0 && (expectedTimeout == 0 || expectedTimeout > this.loginTimeoutCountdown)) { + return this.loginTimeoutCountdown; + } + return expectedTimeout; + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Statement.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Statement.java (.../Statement.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Statement.java (.../Statement.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,2368 +1,105 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import com.mysql.jdbc.exceptions.MySQLTimeoutException; -import com.mysql.jdbc.profiler.ProfileEventSink; -import com.mysql.jdbc.profiler.ProfilerEvent; -import com.mysql.jdbc.util.LRUCache; - -import java.sql.DataTruncation; +import java.io.InputStream; import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.TimerTask; - /** - * A Statement object is used for executing a static SQL statement and obtaining - * the results produced by it. - * - *

- * Only one ResultSet per Statement can be open at any point in time. Therefore, - * if the reading of one ResultSet is interleaved with the reading of another, - * each must have been generated by different Statements. All statement execute - * methods implicitly close a statement's current ResultSet if an open one - * exists. - *

- * - * @author Mark Matthews - * @version $Id: Statement.java 4624 2005-11-28 14:24:29 -0600 (Mon, 28 Nov - * 2005) mmatthews $ - * - * @see java.sql.Statement - * @see ResultSet + * This interface contains methods that are considered the "vendor extension" + * to the JDBC API for MySQL's implementation of java.sql.Statement. + * + * For those looking further into the driver implementation, it is not + * an API that is used for plugability of implementations inside our driver + * (which is why there are still references to StatementImpl throughout the + * code). + * + * @version $Id$ + * */ -public class Statement implements java.sql.Statement { - protected static final String PING_MARKER = "/* ping */"; +public interface Statement extends java.sql.Statement { /** - * Thread used to implement query timeouts...Eventually we could be more - * efficient and have one thread with timers, but this is a straightforward - * and simple way to implement a feature that isn't used all that often. - */ - class CancelTask extends TimerTask { - - long connectionId = 0; - SQLException caughtWhileCancelling = null; - - CancelTask() throws SQLException { - connectionId = connection.getIO().getThreadId(); - } - - public void run() { - - Thread cancelThread = new Thread() { - - public void run() { - Connection cancelConn = null; - java.sql.Statement cancelStmt = null; - - try { - synchronized (cancelTimeoutMutex) { - cancelConn = connection.duplicate(); - cancelStmt = cancelConn.createStatement(); - cancelStmt.execute("KILL QUERY " + connectionId); - wasCancelled = true; - } - } catch (SQLException sqlEx) { - caughtWhileCancelling = sqlEx; - } catch (NullPointerException npe) { - // Case when connection closed while starting to cancel - // We can't easily synchronize this, because then one thread - // can't cancel() a running query - - // ignore, we shouldn't re-throw this, because the connection's - // already closed, so the statement has been timed out. - } finally { - if (cancelStmt != null) { - try { - cancelStmt.close(); - } catch (SQLException sqlEx) { - throw new RuntimeException(sqlEx.toString()); - } - } - - if (cancelConn != null) { - try { - cancelConn.close(); - } catch (SQLException sqlEx) { - throw new RuntimeException(sqlEx.toString()); - } - } - } - } - }; - - cancelThread.start(); - } - } - - /** Mutex to prevent race between returning query results and noticing - that we're timed-out or cancelled. */ - - protected Object cancelTimeoutMutex = new Object(); - - /** Used to generate IDs when profiling. */ - protected static int statementCounter = 1; - - public final static byte USES_VARIABLES_FALSE = 0; - - public final static byte USES_VARIABLES_TRUE = 1; - - public final static byte USES_VARIABLES_UNKNOWN = -1; - - protected boolean wasCancelled = false; - - /** Holds batched commands */ - protected List batchedArgs; - - /** The character converter to use (if available) */ - protected SingleByteCharsetConverter charConverter = null; - - /** The character encoding to use (if available) */ - protected String charEncoding = null; - - /** The connection that created us */ - protected Connection connection = null; - - protected long connectionId = 0; - - /** The catalog in use */ - protected String currentCatalog = null; - - /** Should we process escape codes? */ - protected boolean doEscapeProcessing = true; - - /** If we're profiling, where should events go to? */ - protected ProfileEventSink eventSink = null; - - /** The number of rows to fetch at a time (currently ignored) */ - private int fetchSize = 0; - - /** Has this statement been closed? */ - protected boolean isClosed = false; - - /** The auto_increment value for the last insert */ - protected long lastInsertId = -1; - - /** The max field size for this statement */ - protected int maxFieldSize = MysqlIO.getMaxBuf(); - - /** - * The maximum number of rows to return for this statement (-1 means _all_ - * rows) - */ - protected int maxRows = -1; - - /** Has someone changed this for this statement? */ - protected boolean maxRowsChanged = false; - - /** List of currently-open ResultSets */ - protected List openResults = new ArrayList(); - - /** Are we in pedantic mode? */ - protected boolean pedantic = false; - - /** - * Where this statement was created, only used if profileSql or - * useUsageAdvisor set to true. - */ - protected Throwable pointOfOrigin; - - /** Should we profile? */ - protected boolean profileSQL = false; - - /** The current results */ - protected ResultSet results = null; - - /** The concurrency for this result set (updatable or not) */ - protected int resultSetConcurrency = 0; - - /** The type of this result set (scroll sensitive or in-sensitive) */ - protected int resultSetType = 0; - - /** Used to identify this statement when profiling. */ - protected int statementId; - - /** The timeout for a query */ - protected int timeoutInMillis = 0; - - /** The update count for this statement */ - protected long updateCount = -1; - - /** Should we use the usage advisor? */ - protected boolean useUsageAdvisor = false; - - /** The warnings chain. */ - protected SQLWarning warningChain = null; - - /** - * Should this statement hold results open over .close() irregardless of - * connection's setting? - */ - protected boolean holdResultsOpenOverClose = false; - - protected ArrayList batchedGeneratedKeys = null; - - protected boolean retrieveGeneratedKeys = false; - - protected boolean continueBatchOnError = false; - - protected PingTarget pingTarget = null; - - - /** - * Constructor for a Statement. - * - * @param c - * the Connection instantation that creates us - * @param catalog - * the database name in use when we were created - * - * @throws SQLException - * if an error occurs. - */ - public Statement(Connection c, String catalog) throws SQLException { - if ((c == null) || c.isClosed()) { - throw SQLError.createSQLException( - Messages.getString("Statement.0"), //$NON-NLS-1$ - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); //$NON-NLS-1$ //$NON-NLS-2$ - } - - this.connection = c; - this.connectionId = this.connection.getId(); - - this.currentCatalog = catalog; - this.pedantic = this.connection.getPedantic(); - this.continueBatchOnError = this.connection.getContinueBatchOnError(); - - if (!this.connection.getDontTrackOpenResources()) { - this.connection.registerStatement(this); - } - - // - // Adjust, if we know it - // - - if (this.connection != null) { - this.maxFieldSize = this.connection.getMaxAllowedPacket(); - - int defaultFetchSize = this.connection.getDefaultFetchSize(); - - if (defaultFetchSize != 0) { - setFetchSize(defaultFetchSize); - } - } - - if (this.connection.getUseUnicode()) { - this.charEncoding = this.connection.getEncoding(); - - this.charConverter = this.connection - .getCharsetConverter(this.charEncoding); - } - - boolean profiling = this.connection.getProfileSql() - || this.connection.getUseUsageAdvisor(); - - if (this.connection.getAutoGenerateTestcaseScript() || profiling) { - this.statementId = statementCounter++; - } - - if (profiling) { - this.pointOfOrigin = new Throwable(); - this.profileSQL = this.connection.getProfileSql(); - this.useUsageAdvisor = this.connection.getUseUsageAdvisor(); - this.eventSink = ProfileEventSink.getInstance(this.connection); - } - - int maxRowsConn = this.connection.getMaxRows(); - - if (maxRowsConn != -1) { - setMaxRows(maxRowsConn); - } - } - - /** - * DOCUMENT ME! - * - * @param sql - * DOCUMENT ME! - * - * @throws SQLException - * DOCUMENT ME! - */ - public synchronized void addBatch(String sql) throws SQLException { - if (this.batchedArgs == null) { - this.batchedArgs = new ArrayList(); - } - - if (sql != null) { - this.batchedArgs.add(sql); - } - } - - /** - * Cancels this Statement object if both the DBMS and driver support - * aborting an SQL statement. This method can be used by one thread to - * cancel a statement that is being executed by another thread. - */ - public void cancel() throws SQLException { - if (!this.isClosed && - this.connection != null && - this.connection.versionMeetsMinimum(5, 0, 0)) { - Connection cancelConn = null; - java.sql.Statement cancelStmt = null; - - try { - synchronized (this.cancelTimeoutMutex) { - cancelConn = this.connection.duplicate(); - cancelStmt = cancelConn.createStatement(); - cancelStmt.execute("KILL QUERY " - + this.connection.getIO().getThreadId()); - this.wasCancelled = true; - } - } catch (NullPointerException npe) { - // Case when connection closed while starting to cancel - // We can't easily synchronize this, because then one thread - // can't cancel() a running query - - throw SQLError.createSQLException(Messages - .getString("Statement.49"), //$NON-NLS-1$ - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); //$NON-NLS-1$ - } finally { - if (cancelStmt != null) { - cancelStmt.close(); - } - - if (cancelConn != null) { - cancelConn.close(); - } - } - - } - } - - // --------------------------JDBC 2.0----------------------------- - - /** - * Checks if closed() has been called, and throws an exception if so - * - * @throws SQLException - * if this statement has been closed - */ - protected void checkClosed() throws SQLException { - if (this.isClosed) { - throw SQLError.createSQLException(Messages - .getString("Statement.49"), //$NON-NLS-1$ - SQLError.SQL_STATE_CONNECTION_NOT_OPEN); //$NON-NLS-1$ - } - } - - /** - * Checks if the given SQL query with the given first non-ws char is a DML - * statement. Throws an exception if it is. - * - * @param sql - * the SQL to check - * @param firstStatementChar - * the UC first non-ws char of the statement - * - * @throws SQLException - * if the statement contains DML - */ - protected void checkForDml(String sql, char firstStatementChar) - throws SQLException { - if ((firstStatementChar == 'I') || (firstStatementChar == 'U') - || (firstStatementChar == 'D') || (firstStatementChar == 'A') - || (firstStatementChar == 'C')) { - String noCommentSql = StringUtils.stripComments(sql, - "'\"", "'\"", true, false, true, true); - - if (StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "INSERT") //$NON-NLS-1$ - || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "UPDATE") //$NON-NLS-1$ - || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DELETE") //$NON-NLS-1$ - || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DROP") //$NON-NLS-1$ - || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "CREATE") //$NON-NLS-1$ - || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "ALTER")) { //$NON-NLS-1$ - throw SQLError.createSQLException(Messages - .getString("Statement.57"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - } - } - - /** - * Method checkNullOrEmptyQuery. - * - * @param sql - * the SQL to check - * - * @throws SQLException - * if query is null or empty. - */ - protected void checkNullOrEmptyQuery(String sql) throws SQLException { - if (sql == null) { - throw SQLError.createSQLException(Messages - .getString("Statement.59"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ - } - - if (sql.length() == 0) { - throw SQLError.createSQLException(Messages - .getString("Statement.61"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - /** - * JDBC 2.0 Make the set of commands in the current batch empty. This method - * is optional. - * - * @exception SQLException - * if a database-access error occurs, or the driver does not - * support batch statements - */ - public synchronized void clearBatch() throws SQLException { - if (this.batchedArgs != null) { - this.batchedArgs.clear(); - } - } - - /** - * After this call, getWarnings returns null until a new warning is reported - * for this Statement. - * - * @exception SQLException - * if a database access error occurs (why?) - */ - public void clearWarnings() throws SQLException { - this.warningChain = null; - } - - /** - * In many cases, it is desirable to immediately release a Statement's - * database and JDBC resources instead of waiting for this to happen when it - * is automatically closed. The close method provides this immediate - * release. - * - *

- * Note: A Statement is automatically closed when it is garbage - * collected. When a Statement is closed, its current ResultSet, if one - * exists, is also closed. - *

- * - * @exception SQLException - * if a database access error occurs - */ - public void close() throws SQLException { - realClose(true, true); - } - - /** - * Close any open result sets that have been 'held open' - */ - protected void closeAllOpenResults() { - if (this.openResults != null) { - for (Iterator iter = this.openResults.iterator(); iter.hasNext();) { - ResultSet element = (ResultSet) iter.next(); - - try { - element.realClose(false); - } catch (SQLException sqlEx) { - AssertionFailedException.shouldNotHappen(sqlEx); - } - } - - this.openResults.clear(); - } - } - - /** - * @param sql - * @return - */ - private ResultSet createResultSetUsingServerFetch(String sql) - throws SQLException { - java.sql.PreparedStatement pStmt = this.connection.prepareStatement( - sql, this.resultSetType, this.resultSetConcurrency); - - pStmt.setFetchSize(this.fetchSize); - - if (this.maxRows > -1) { - pStmt.setMaxRows(this.maxRows); - } - - pStmt.execute(); - - // - // Need to be able to get resultset irrespective if we issued DML or - // not to make this work. - // - ResultSet rs = ((com.mysql.jdbc.Statement) pStmt) - .getResultSetInternal(); - - rs - .setStatementUsedForFetchingRows((com.mysql.jdbc.PreparedStatement) pStmt); - - this.results = rs; - - return rs; - } - - /** - * We only stream result sets when they are forward-only, read-only, and the - * fetch size has been set to Integer.MIN_VALUE - * - * @return true if this result set should be streamed row at-a-time, rather - * than read all at once. - */ - protected boolean createStreamingResultSet() { - return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY) - && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) && (this.fetchSize == Integer.MIN_VALUE)); - } - - /** * Workaround for containers that 'check' for sane values of - * Statement.setFetchSize(). - * + * Statement.setFetchSize() so that applications can use + * the Java variant of libmysql's mysql_use_result() behavior. + * * @throws SQLException */ - public void enableStreamingResults() throws SQLException { - setFetchSize(Integer.MIN_VALUE); - setResultSetType(ResultSet.TYPE_FORWARD_ONLY); - } + public abstract void enableStreamingResults() throws SQLException; /** - * Execute a SQL statement that may return multiple results. We don't have - * to worry about this since we do not support multiple ResultSets. You can - * use getResultSet or getUpdateCount to retrieve the result. - * - * @param sql - * any SQL statement - * - * @return true if the next result is a ResulSet, false if it is an update - * count or there are no more results - * - * @exception SQLException - * if a database access error occurs - */ - public boolean execute(String sql) throws SQLException { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - synchronized (this.cancelTimeoutMutex) { - this.wasCancelled = false; - } - - checkNullOrEmptyQuery(sql); - - checkClosed(); - - char firstNonWsChar = StringUtils.firstNonWsCharUc(sql); - - boolean isSelect = true; - - if (firstNonWsChar != 'S') { - isSelect = false; - - if (locallyScopedConn.isReadOnly()) { - throw SQLError.createSQLException(Messages - .getString("Statement.27") //$NON-NLS-1$ - + Messages.getString("Statement.28"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - } - - if (this.doEscapeProcessing) { - Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, - locallyScopedConn.serverSupportsConvertFn(), locallyScopedConn); - - if (escapedSqlResult instanceof String) { - sql = (String) escapedSqlResult; - } else { - sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; - } - } - - if (this.results != null) { - if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) { - this.results.realClose(false); - } - } - - if (firstNonWsChar == '/') { - if (sql.startsWith(PING_MARKER)) { - doPingInstead(); - - return true; - } - } - - CachedResultSetMetaData cachedMetaData = null; - - ResultSet rs = null; - - // If there isn't a limit clause in the SQL - // then limit the number of rows to return in - // an efficient manner. Only do this if - // setMaxRows() hasn't been used on any Statements - // generated from the current Connection (saves - // a query, and network traffic). - - this.batchedGeneratedKeys = null; - - if (useServerFetch()) { - rs = createResultSetUsingServerFetch(sql); - } else { - CancelTask timeoutTask = null; - - String oldCatalog = null; - - try { - if (locallyScopedConn.getEnableQueryTimeouts() && - this.timeoutInMillis != 0 - && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { - timeoutTask = new CancelTask(); - Connection.getCancelTimer().schedule(timeoutTask, - this.timeoutInMillis); - } - - - - if (!locallyScopedConn.getCatalog().equals( - this.currentCatalog)) { - oldCatalog = locallyScopedConn.getCatalog(); - locallyScopedConn.setCatalog(this.currentCatalog); - } - - // - // Check if we have cached metadata for this query... - // - if (locallyScopedConn.getCacheResultSetMetadata()) { - cachedMetaData = locallyScopedConn.getCachedMetaData(sql); - } - - // - // Only apply max_rows to selects - // - if (locallyScopedConn.useMaxRows()) { - int rowLimit = -1; - - if (isSelect) { - if (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1) { //$NON-NLS-1$ - rowLimit = this.maxRows; - } else { - if (this.maxRows <= 0) { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, //$NON-NLS-1$ - null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, - this.currentCatalog, true); //$NON-NLS-1$ - } else { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, //$NON-NLS-1$ - -1, - null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, - this.currentCatalog, true); //$NON-NLS-1$ - } - } - } else { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$ - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.currentCatalog, - true); //$NON-NLS-1$ - } - - // Finally, execute the query - rs = locallyScopedConn.execSQL(this, sql, rowLimit, null, - this.resultSetType, this.resultSetConcurrency, - createStreamingResultSet(), - this.currentCatalog, (cachedMetaData == null)); - } else { - rs = locallyScopedConn.execSQL(this, sql, -1, null, - this.resultSetType, this.resultSetConcurrency, - createStreamingResultSet(), - this.currentCatalog, (cachedMetaData == null)); - } - - if (timeoutTask != null) { - if (timeoutTask.caughtWhileCancelling != null) { - throw timeoutTask.caughtWhileCancelling; - } - - timeoutTask.cancel(); - timeoutTask = null; - } - - synchronized (this.cancelTimeoutMutex) { - if (this.wasCancelled) { - this.wasCancelled = false; - throw new MySQLTimeoutException(); - } - } - } finally { - if (timeoutTask != null) { - timeoutTask.cancel(); - } - - if (oldCatalog != null) { - locallyScopedConn.setCatalog(oldCatalog); - } - } - } - - this.lastInsertId = rs.getUpdateID(); - - if (rs != null) { - this.results = rs; - - rs.setFirstCharOfQuery(firstNonWsChar); - - if (rs.reallyResult()) { - if (cachedMetaData != null) { - locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData, - this.results); - } else { - if (this.connection.getCacheResultSetMetadata()) { - locallyScopedConn.initializeResultsMetadataFromCache(sql, - null /* will be created */, this.results); - } - } - } - } - - return ((rs != null) && rs.reallyResult()); - } - } - - /** - * @see Statement#execute(String, int) - */ - public boolean execute(String sql, int returnGeneratedKeys) - throws SQLException { - - - if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - // If this is a 'REPLACE' query, we need to be able to parse - // the 'info' message returned from the server to determine - // the actual number of keys generated. - boolean readInfoMsgState = this.connection - .isReadInfoMsgEnabled(); - locallyScopedConn.setReadInfoMsgEnabled(true); - - try { - return execute(sql); - } finally { - locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); - } - } - } - - return execute(sql); - } - - /** - * @see Statement#execute(String, int[]) - */ - public boolean execute(String sql, int[] generatedKeyIndices) - throws SQLException { - if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - // If this is a 'REPLACE' query, we need to be able to parse - // the 'info' message returned from the server to determine - // the actual number of keys generated. - boolean readInfoMsgState = locallyScopedConn - .isReadInfoMsgEnabled(); - locallyScopedConn.setReadInfoMsgEnabled(true); - - try { - return execute(sql); - } finally { - locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); - } - } - } - - return execute(sql); - } - - /** - * @see Statement#execute(String, String[]) - */ - public boolean execute(String sql, String[] generatedKeyNames) - throws SQLException { - if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - // If this is a 'REPLACE' query, we need to be able to parse - // the 'info' message returned from the server to determine - // the actual number of keys generated. - boolean readInfoMsgState = this.connection - .isReadInfoMsgEnabled(); - locallyScopedConn.setReadInfoMsgEnabled(true); - - try { - return execute(sql); - } finally { - locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); - } - } - } - - return execute(sql); - } - - /** - * JDBC 2.0 Submit a batch of commands to the database for execution. This - * method is optional. - * - * @return an array of update counts containing one element for each command - * in the batch. The array is ordered according to the order in - * which commands were inserted into the batch - * - * @exception SQLException - * if a database-access error occurs, or the driver does not - * support batch statements - * @throws java.sql.BatchUpdateException - * DOCUMENT ME! - */ - public synchronized int[] executeBatch() throws SQLException { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - if (locallyScopedConn.isReadOnly()) { - throw SQLError.createSQLException(Messages - .getString("Statement.34") //$NON-NLS-1$ - + Messages.getString("Statement.35"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - - if (this.results != null) { - if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) { - this.results.realClose(false); - } - } - - synchronized (locallyScopedConn.getMutex()) { - if (this.batchedArgs == null || this.batchedArgs.size() == 0) { - return new int[0]; - } - - try { - this.retrieveGeneratedKeys = true; - - int[] updateCounts = null; - - if (this.batchedArgs != null) { - int nbrCommands = this.batchedArgs.size(); - - this.batchedGeneratedKeys = new ArrayList(this.batchedArgs.size()); - - boolean multiQueriesEnabled = locallyScopedConn.getAllowMultiQueries(); - - if (locallyScopedConn.versionMeetsMinimum(4, 1, 1) && - (multiQueriesEnabled || - (locallyScopedConn.getRewriteBatchedStatements() && - nbrCommands > 4))) { - return executeBatchUsingMultiQueries(multiQueriesEnabled, nbrCommands); - } - - updateCounts = new int[nbrCommands]; - - for (int i = 0; i < nbrCommands; i++) { - updateCounts[i] = -3; - } - - SQLException sqlEx = null; - - int commandIndex = 0; - - for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { - try { - updateCounts[commandIndex] = executeUpdate((String) this.batchedArgs - .get(commandIndex), true); - getBatchedGeneratedKeys(); - } catch (SQLException ex) { - updateCounts[commandIndex] = EXECUTE_FAILED; - - if (this.continueBatchOnError) { - sqlEx = ex; - } else { - int[] newUpdateCounts = new int[commandIndex]; - System.arraycopy(updateCounts, 0, - newUpdateCounts, 0, commandIndex); - - throw new java.sql.BatchUpdateException(ex - .getMessage(), ex.getSQLState(), ex - .getErrorCode(), newUpdateCounts); - } - } - } - - if (sqlEx != null) { - throw new java.sql.BatchUpdateException(sqlEx - .getMessage(), sqlEx.getSQLState(), sqlEx - .getErrorCode(), updateCounts); - } - } - - return (updateCounts != null) ? updateCounts : new int[0]; - } finally { - this.retrieveGeneratedKeys = false; - - clearBatch(); - } - } - } - - /** - * Rewrites batch into a single query to send to the server. This method - * will constrain each batch to be shorter than max_allowed_packet on the - * server. - * - * @return update counts in the same manner as executeBatch() + * Resets this statements fetch size and result set type to the values + * they had before enableStreamingResults() was called. + * * @throws SQLException */ - private int[] executeBatchUsingMultiQueries(boolean multiQueriesEnabled, - int nbrCommands) throws SQLException { + public abstract void disableStreamingResults() throws SQLException; - Connection locallyScopedConn = this.connection; - - if (!multiQueriesEnabled) { - locallyScopedConn.getIO().enableMultiQueries(); - } - - java.sql.Statement batchStmt = null; - - try { - int[] updateCounts = new int[nbrCommands]; - - for (int i = 0; i < nbrCommands; i++) { - updateCounts[i] = -3; - } - - int commandIndex = 0; - - StringBuffer queryBuf = new StringBuffer(); - - - - batchStmt = locallyScopedConn.createStatement(); - - - int counter = 0; - - int numberOfBytesPerChar = 1; - - String connectionEncoding = locallyScopedConn.getEncoding(); - - if (StringUtils.startsWithIgnoreCase(connectionEncoding, "utf")) { - numberOfBytesPerChar = 3; - } else if (CharsetMapping.isMultibyteCharset(connectionEncoding)) { - numberOfBytesPerChar = 2; - } - - int escapeAdjust = 1; - - if (this.doEscapeProcessing) { - escapeAdjust = 2; /* We assume packet _could_ grow by this amount, as we're not - sure how big statement will end up after - escape processing */ - } - - for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { - String nextQuery = (String) this.batchedArgs.get(commandIndex); - - if (((((queryBuf.length() + nextQuery.length()) - * numberOfBytesPerChar) + 1 /* for semicolon */ - + MysqlIO.HEADER_LENGTH) * escapeAdjust) + 32 > this.connection - .getMaxAllowedPacket()) { - batchStmt.execute(queryBuf.toString()); - - updateCounts[counter++] = batchStmt.getUpdateCount(); - long generatedKeyStart = ((com.mysql.jdbc.Statement)batchStmt).getLastInsertID(); - byte[][] row = new byte[1][]; - row[0] = Long.toString(generatedKeyStart++).getBytes(); - this.batchedGeneratedKeys.add(row); - - while (batchStmt.getMoreResults() - || batchStmt.getUpdateCount() != -1) { - updateCounts[counter++] = batchStmt.getUpdateCount(); - row = new byte[1][]; - row[0] = Long.toString(generatedKeyStart++).getBytes(); - this.batchedGeneratedKeys.add(row); - } - - queryBuf = new StringBuffer(); - } - - queryBuf.append(nextQuery); - queryBuf.append(";"); - } - - if (queryBuf.length() > 0) { - batchStmt.execute(queryBuf.toString()); - - long generatedKeyStart = ((com.mysql.jdbc.Statement)batchStmt).getLastInsertID(); - byte[][] row = new byte[1][]; - row[0] = Long.toString(generatedKeyStart++).getBytes(); - this.batchedGeneratedKeys.add(row); - - updateCounts[counter++] = batchStmt.getUpdateCount(); - - while (batchStmt.getMoreResults() - || batchStmt.getUpdateCount() != -1) { - updateCounts[counter++] = batchStmt.getUpdateCount(); - row = new byte[1][]; - row[0] = Long.toString(generatedKeyStart++).getBytes(); - this.batchedGeneratedKeys.add(row); - } - } - - return (updateCounts != null) ? updateCounts : new int[0]; - } finally { - try { - if (batchStmt != null) { - batchStmt.close(); - } - } finally { - if (!multiQueriesEnabled) { - locallyScopedConn.getIO().disableMultiQueries(); - } - } - } - } - /** - * Execute a SQL statement that retruns a single ResultSet - * - * @param sql - * typically a static SQL SELECT statement - * - * @return a ResulSet that contains the data produced by the query - * - * @exception SQLException - * if a database access error occurs + * Sets an InputStream instance that will be used to send data + * to the MySQL server for a "LOAD DATA LOCAL INFILE" statement + * rather than a FileInputStream or URLInputStream that represents + * the path given as an argument to the statement. + * + * This stream will be read to completion upon execution of a + * "LOAD DATA LOCAL INFILE" statement, and will automatically + * be closed by the driver, so it needs to be reset + * before each call to execute*() that would cause the MySQL + * server to request data to fulfill the request for + * "LOAD DATA LOCAL INFILE". + * + * If this value is set to NULL, the driver will revert to using + * a FileInputStream or URLInputStream as required. */ - public java.sql.ResultSet executeQuery(String sql) - throws SQLException { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - synchronized (this.cancelTimeoutMutex) { - this.wasCancelled = false; - } - - checkNullOrEmptyQuery(sql); + public abstract void setLocalInfileInputStream(InputStream stream); - if (this.doEscapeProcessing) { - Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, - locallyScopedConn.serverSupportsConvertFn(), this.connection); - - if (escapedSqlResult instanceof String) { - sql = (String) escapedSqlResult; - } else { - sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; - } - } - - char firstStatementChar = StringUtils.firstNonWsCharUc(sql, - findStartOfStatement(sql)); - - if (sql.charAt(0) == '/') { - if (sql.startsWith(PING_MARKER)) { - doPingInstead(); - - return this.results; - } - } - - checkForDml(sql, firstStatementChar); - - if (this.results != null) { - if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) { - this.results.realClose(false); - } - } - - CachedResultSetMetaData cachedMetaData = null; - - // If there isn't a limit clause in the SQL - // then limit the number of rows to return in - // an efficient manner. Only do this if - // setMaxRows() hasn't been used on any Statements - // generated from the current Connection (saves - // a query, and network traffic). - - if (useServerFetch()) { - this.results = createResultSetUsingServerFetch(sql); - - return this.results; - } - - CancelTask timeoutTask = null; - - String oldCatalog = null; - - try { - if (locallyScopedConn.getEnableQueryTimeouts() && - this.timeoutInMillis != 0 - && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { - timeoutTask = new CancelTask(); - Connection.getCancelTimer().schedule(timeoutTask, - this.timeoutInMillis); - } - - if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) { - oldCatalog = locallyScopedConn.getCatalog(); - locallyScopedConn.setCatalog(this.currentCatalog); - } - - // - // Check if we have cached metadata for this query... - // - if (locallyScopedConn.getCacheResultSetMetadata()) { - cachedMetaData = locallyScopedConn.getCachedMetaData(sql); - } - - if (locallyScopedConn.useMaxRows()) { - // We need to execute this all together - // So synchronize on the Connection's mutex (because - // even queries going through there synchronize - // on the connection - if (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1) { //$NON-NLS-1$ - this.results = locallyScopedConn.execSQL(this, sql, - this.maxRows, null, this.resultSetType, - this.resultSetConcurrency, - createStreamingResultSet(), - this.currentCatalog, (cachedMetaData == null)); - } else { - if (this.maxRows <= 0) { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$ - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.currentCatalog, - true); //$NON-NLS-1$ - } else { - locallyScopedConn - .execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, -1, //$NON-NLS-1$ - null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, - false, this.currentCatalog, - true); //$NON-NLS-1$ - } - - this.results = locallyScopedConn.execSQL(this, sql, -1, - null, this.resultSetType, - this.resultSetConcurrency, - createStreamingResultSet(), - this.currentCatalog, (cachedMetaData == null)); - - if (oldCatalog != null) { - locallyScopedConn.setCatalog(oldCatalog); - } - } - } else { - this.results = locallyScopedConn.execSQL(this, sql, -1, null, - this.resultSetType, this.resultSetConcurrency, - createStreamingResultSet(), - this.currentCatalog, (cachedMetaData == null)); - } - - if (timeoutTask != null) { - if (timeoutTask.caughtWhileCancelling != null) { - throw timeoutTask.caughtWhileCancelling; - } - - timeoutTask.cancel(); - timeoutTask = null; - } - - synchronized (this.cancelTimeoutMutex) { - if (this.wasCancelled) { - this.wasCancelled = false; - throw new MySQLTimeoutException(); - } - } - } finally { - if (timeoutTask != null) { - timeoutTask.cancel(); - } - - if (oldCatalog != null) { - locallyScopedConn.setCatalog(oldCatalog); - } - } - - this.lastInsertId = this.results.getUpdateID(); - - if (cachedMetaData != null) { - locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData, - this.results); - } else { - if (this.connection.getCacheResultSetMetadata()) { - locallyScopedConn.initializeResultsMetadataFromCache(sql, - null /* will be created */, this.results); - } - } - - return this.results; - } - } - - protected void doPingInstead() throws SQLException { - if (this.pingTarget != null) { - this.pingTarget.doPing(); - } else { - this.connection.ping(); - } - - ResultSet fakeSelectOneResultSet = generatePingResultSet(); - this.results = fakeSelectOneResultSet; - } - - protected ResultSet generatePingResultSet() throws SQLException { - Field[] fields = { new Field(null, "1", Types.BIGINT, 1) }; - ArrayList rows = new ArrayList(); - byte[] colVal = new byte[] { (byte) '1' }; - - rows.add(new byte[][] { colVal }); - - return (ResultSet) DatabaseMetaData.buildResultSet(fields, rows, - this.connection); - } - /** - * Execute a SQL INSERT, UPDATE or DELETE statement. In addition SQL - * statements that return nothing such as SQL DDL statements can be executed - * Any IDs generated for AUTO_INCREMENT fields can be retrieved by casting - * this Statement to org.gjt.mm.mysql.Statement and calling the - * getLastInsertID() method. - * - * @param sql - * a SQL statement - * - * @return either a row count, or 0 for SQL commands - * - * @exception SQLException - * if a database access error occurs + * Returns the InputStream instance that will be used to send + * data in response to a "LOAD DATA LOCAL INFILE" statement. + * + * This method returns NULL if no such stream has been set + * via setLocalInfileInputStream(). */ - public int executeUpdate(String sql) throws SQLException { - return executeUpdate(sql, false); - } + public abstract InputStream getLocalInfileInputStream(); - protected int executeUpdate(String sql, boolean isBatch) - throws SQLException { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - char firstStatementChar = StringUtils.firstNonWsCharUc(sql, - findStartOfStatement(sql)); + public void setPingTarget(PingTarget pingTarget); - ResultSet rs = null; - - synchronized (locallyScopedConn.getMutex()) { - synchronized (this.cancelTimeoutMutex) { - this.wasCancelled = false; - } + public ExceptionInterceptor getExceptionInterceptor(); - checkNullOrEmptyQuery(sql); - - if (this.doEscapeProcessing) { - Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, - this.connection.serverSupportsConvertFn(), this.connection); - - if (escapedSqlResult instanceof String) { - sql = (String) escapedSqlResult; - } else { - sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; - } - } - - if (locallyScopedConn.isReadOnly()) { - throw SQLError.createSQLException(Messages - .getString("Statement.42") //$NON-NLS-1$ - + Messages.getString("Statement.43"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - - if (StringUtils.startsWithIgnoreCaseAndWs(sql, "select")) { //$NON-NLS-1$ - throw SQLError.createSQLException(Messages - .getString("Statement.46"), //$NON-NLS-1$ - "01S03"); //$NON-NLS-1$ - } - - if (this.results != null) { - if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) { - this.results.realClose(false); - } - } - - // The checking and changing of catalogs - // must happen in sequence, so synchronize - // on the same mutex that _conn is using - - CancelTask timeoutTask = null; - - String oldCatalog = null; - - try { - if (locallyScopedConn.getEnableQueryTimeouts() && - this.timeoutInMillis != 0 - && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { - timeoutTask = new CancelTask(); - Connection.getCancelTimer().schedule(timeoutTask, - this.timeoutInMillis); - } - - if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) { - oldCatalog = locallyScopedConn.getCatalog(); - locallyScopedConn.setCatalog(this.currentCatalog); - } - - // - // Only apply max_rows to selects - // - if (locallyScopedConn.useMaxRows()) { - locallyScopedConn.execSQL( - this, - "SET OPTION SQL_SELECT_LIMIT=DEFAULT", //$NON-NLS-1$ - -1, null, java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.currentCatalog, true); - } - - rs = locallyScopedConn.execSQL(this, sql, -1, null, - java.sql.ResultSet.TYPE_FORWARD_ONLY, - java.sql.ResultSet.CONCUR_READ_ONLY, false, - this.currentCatalog, - true /* force read of field info on DML */, - isBatch); - - if (timeoutTask != null) { - if (timeoutTask.caughtWhileCancelling != null) { - throw timeoutTask.caughtWhileCancelling; - } - - timeoutTask.cancel(); - timeoutTask = null; - } - - synchronized (this.cancelTimeoutMutex) { - if (this.wasCancelled) { - this.wasCancelled = false; - throw new MySQLTimeoutException(); - } - } - } finally { - if (timeoutTask != null) { - timeoutTask.cancel(); - } - - if (oldCatalog != null) { - locallyScopedConn.setCatalog(oldCatalog); - } - } - } - - this.results = rs; - - rs.setFirstCharOfQuery(firstStatementChar); - - this.updateCount = rs.getUpdateCount(); - - int truncatedUpdateCount = 0; - - if (this.updateCount > Integer.MAX_VALUE) { - truncatedUpdateCount = Integer.MAX_VALUE; - } else { - truncatedUpdateCount = (int) this.updateCount; - } - - this.lastInsertId = rs.getUpdateID(); - - return truncatedUpdateCount; - } - - /** - * @see Statement#executeUpdate(String, int) + /** + * Callback for result set instances to remove them from the Set that + * tracks them per-statement */ - public int executeUpdate(String sql, int returnGeneratedKeys) - throws SQLException { - if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - // If this is a 'REPLACE' query, we need to be able to parse - // the 'info' message returned from the server to determine - // the actual number of keys generated. - boolean readInfoMsgState = locallyScopedConn - .isReadInfoMsgEnabled(); - locallyScopedConn.setReadInfoMsgEnabled(true); - - try { - return executeUpdate(sql); - } finally { - locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); - } - } - } - - return executeUpdate(sql); - } - - /** - * @see Statement#executeUpdate(String, int[]) - */ - public int executeUpdate(String sql, int[] generatedKeyIndices) - throws SQLException { - if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - // If this is a 'REPLACE' query, we need to be able to parse - // the 'info' message returned from the server to determine - // the actual number of keys generated. - boolean readInfoMsgState = locallyScopedConn - .isReadInfoMsgEnabled(); - locallyScopedConn.setReadInfoMsgEnabled(true); - - try { - return executeUpdate(sql); - } finally { - locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); - } - } - } - - return executeUpdate(sql); - } - - /** - * @see Statement#executeUpdate(String, String[]) - */ - public int executeUpdate(String sql, String[] generatedKeyNames) - throws SQLException { - if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) { - checkClosed(); - - Connection locallyScopedConn = this.connection; - - synchronized (locallyScopedConn.getMutex()) { - // If this is a 'REPLACE' query, we need to be able to parse - // the 'info' message returned from the server to determine - // the actual number of keys generated. - boolean readInfoMsgState = this.connection - .isReadInfoMsgEnabled(); - locallyScopedConn.setReadInfoMsgEnabled(true); - - try { - return executeUpdate(sql); - } finally { - locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); - } - } - } - - return executeUpdate(sql); - } - - - - /** - * Optimization to only use one calendar per-session, or calculate it for - * each call, depending on user configuration - */ - protected Calendar getCalendarInstanceForSessionOrNew() { - if (this.connection != null) { - return this.connection.getCalendarInstanceForSessionOrNew(); - } else { - // punt, no connection around - return new GregorianCalendar(); - } - } - - /** - * JDBC 2.0 Return the Connection that produced the Statement. - * - * @return the Connection that produced the Statement - * - * @throws SQLException - * if an error occurs - */ - public java.sql.Connection getConnection() throws SQLException { - return this.connection; - } - - /** - * JDBC 2.0 Determine the fetch direction. - * - * @return the default fetch direction - * - * @exception SQLException - * if a database-access error occurs - */ - public int getFetchDirection() throws SQLException { - return java.sql.ResultSet.FETCH_FORWARD; - } - - /** - * JDBC 2.0 Determine the default fetch size. - * - * @return the number of rows to fetch at a time - * - * @throws SQLException - * if an error occurs - */ - public int getFetchSize() throws SQLException { - return this.fetchSize; - } - - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - * - * @throws SQLException - * DOCUMENT ME! - */ - public java.sql.ResultSet getGeneratedKeys() - throws SQLException { - if (this.batchedGeneratedKeys == null) { - return getGeneratedKeysInternal(); - } - - Field[] fields = new Field[1]; - fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$ - fields[0].setConnection(this.connection); - - return new com.mysql.jdbc.ResultSet(this.currentCatalog, fields, - new RowDataStatic(this.batchedGeneratedKeys), this.connection, - this); - } + + public abstract void removeOpenResultSet(ResultSetInternalMethods rs); - /* - * Needed because there's no concept of super.super to get to this - * implementation from ServerPreparedStatement when dealing with batched - * updates. - */ - protected java.sql.ResultSet getGeneratedKeysInternal() - throws SQLException { - Field[] fields = new Field[1]; - fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$ - fields[0].setConnection(this.connection); - - ArrayList rowSet = new ArrayList(); - - long beginAt = getLastInsertID(); - int numKeys = getUpdateCount(); - - if (this.results != null) { - String serverInfo = this.results.getServerInfo(); - - // - // Only parse server info messages for 'REPLACE' - // queries - // - if ((numKeys > 0) && (this.results.getFirstCharOfQuery() == 'R') - && (serverInfo != null) && (serverInfo.length() > 0)) { - numKeys = getRecordCountFromInfo(serverInfo); - } - - if ((beginAt > 0) && (numKeys > 0)) { - for (int i = 0; i < numKeys; i++) { - byte[][] row = new byte[1][]; - row[0] = Long.toString(beginAt++).getBytes(); - rowSet.add(row); - } - } - } - - return new com.mysql.jdbc.ResultSet(this.currentCatalog, fields, - new RowDataStatic(rowSet), this.connection, this); - } - /** - * Returns the id used when profiling - * - * @return the id used when profiling. - */ - protected int getId() { - return this.statementId; - } - - /** - * getLastInsertID returns the value of the auto_incremented key after an - * executeQuery() or excute() call. - * - *

- * This gets around the un-threadsafe behavior of "select LAST_INSERT_ID()" - * which is tied to the Connection that created this Statement, and - * therefore could have had many INSERTS performed before one gets a chance - * to call "select LAST_INSERT_ID()". - *

- * - * @return the last update ID. - */ - public long getLastInsertID() { - return this.lastInsertId; - } - - /** - * getLongUpdateCount returns the current result as an update count, if the - * result is a ResultSet or there are no more results, -1 is returned. It - * should only be called once per result. - * - *

- * This method returns longs as MySQL server versions newer than 3.22.4 - * return 64-bit values for update counts - *

- * - * @return the current update count. - */ - public long getLongUpdateCount() { - if (this.results == null) { - return -1; - } - - if (this.results.reallyResult()) { - return -1; - } - - return this.updateCount; - } - - /** - * The maxFieldSize limit (in bytes) is the maximum amount of data returned - * for any column value; it only applies to BINARY, VARBINARY, - * LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR columns. If the limit is - * exceeded, the excess data is silently discarded. - * - * @return the current max column size limit; zero means unlimited - * - * @exception SQLException - * if a database access error occurs - */ - public int getMaxFieldSize() throws SQLException { - return this.maxFieldSize; - } - - /** - * The maxRows limit is set to limit the number of rows that any ResultSet - * can contain. If the limit is exceeded, the excess rows are silently - * dropped. - * - * @return the current maximum row limit; zero means unlimited - * - * @exception SQLException - * if a database access error occurs - */ - public int getMaxRows() throws SQLException { - if (this.maxRows <= 0) { - return 0; - } - - return this.maxRows; - } - - /** - * getMoreResults moves to a Statement's next result. If it returns true, - * this result is a ResulSet. - * - * @return true if the next ResultSet is valid - * - * @exception SQLException - * if a database access error occurs - */ - public boolean getMoreResults() throws SQLException { - return getMoreResults(CLOSE_CURRENT_RESULT); - } - - /** - * @see Statement#getMoreResults(int) - */ - public boolean getMoreResults(int current) throws SQLException { - - if (this.results == null) { - return false; - } - - ResultSet nextResultSet = this.results.getNextResultSet(); - - switch (current) { - case java.sql.Statement.CLOSE_CURRENT_RESULT: - - if (this.results != null) { - this.results.close(); - this.results.clearNextResult(); - } - - break; - - case java.sql.Statement.CLOSE_ALL_RESULTS: - - if (this.results != null) { - this.results.close(); - this.results.clearNextResult(); - } - - closeAllOpenResults(); - - break; - - case java.sql.Statement.KEEP_CURRENT_RESULT: - if (!this.connection.getDontTrackOpenResources()) { - this.openResults.add(this.results); - } - - this.results.clearNextResult(); // nobody besides us should - // ever need this value... - break; - - default: - throw SQLError.createSQLException(Messages - .getString("Statement.19"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - - this.results = nextResultSet; - - if (this.results == null) { - this.updateCount = -1; - this.lastInsertId = -1; - } else if (this.results.reallyResult()) { - this.updateCount = -1; - this.lastInsertId = -1; - } else { - this.updateCount = this.results.getUpdateCount(); - this.lastInsertId = this.results.getUpdateID(); - } - - return ((this.results != null) && this.results.reallyResult()) ? true - : false; - } - - /** - * The queryTimeout limit is the number of seconds the driver will wait for - * a Statement to execute. If the limit is exceeded, a SQLException is - * thrown. - * - * @return the current query timeout limit in seconds; 0 = unlimited - * - * @exception SQLException - * if a database access error occurs - */ - public int getQueryTimeout() throws SQLException { - return this.timeoutInMillis / 1000; - } - - /** - * Parses actual record count from 'info' message - * - * @param serverInfo - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - private int getRecordCountFromInfo(String serverInfo) { - StringBuffer recordsBuf = new StringBuffer(); - int recordsCount = 0; - int duplicatesCount = 0; - - char c = (char) 0; - - int length = serverInfo.length(); - int i = 0; - - for (; i < length; i++) { - c = serverInfo.charAt(i); - - if (Character.isDigit(c)) { - break; - } - } - - recordsBuf.append(c); - i++; - - for (; i < length; i++) { - c = serverInfo.charAt(i); - - if (!Character.isDigit(c)) { - break; - } - - recordsBuf.append(c); - } - - recordsCount = Integer.parseInt(recordsBuf.toString()); - - StringBuffer duplicatesBuf = new StringBuffer(); - - for (; i < length; i++) { - c = serverInfo.charAt(i); - - if (Character.isDigit(c)) { - break; - } - } - - duplicatesBuf.append(c); - i++; - - for (; i < length; i++) { - c = serverInfo.charAt(i); - - if (!Character.isDigit(c)) { - break; - } - - duplicatesBuf.append(c); - } - - duplicatesCount = Integer.parseInt(duplicatesBuf.toString()); - - return recordsCount - duplicatesCount; - } - - /** - * getResultSet returns the current result as a ResultSet. It should only be - * called once per result. - * - * @return the current result set; null if there are no more - * - * @exception SQLException - * if a database access error occurs (why?) - */ - public java.sql.ResultSet getResultSet() throws SQLException { - return ((this.results != null) && this.results.reallyResult()) ? (java.sql.ResultSet) this.results - : null; - } - - /** - * JDBC 2.0 Determine the result set concurrency. - * - * @return CONCUR_UPDATABLE or CONCUR_READONLY - * - * @throws SQLException - * if an error occurs - */ - public int getResultSetConcurrency() throws SQLException { - return this.resultSetConcurrency; - } - - /** - * @see Statement#getResultSetHoldability() - */ - public int getResultSetHoldability() throws SQLException { - return java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; - } - - protected ResultSet getResultSetInternal() { - return this.results; - } - - /** - * JDBC 2.0 Determine the result set type. - * - * @return the ResultSet type (SCROLL_SENSITIVE or SCROLL_INSENSITIVE) - * - * @throws SQLException - * if an error occurs. - */ - public int getResultSetType() throws SQLException { - return this.resultSetType; - } - - /** - * getUpdateCount returns the current result as an update count, if the - * result is a ResultSet or there are no more results, -1 is returned. It - * should only be called once per result. - * - * @return the current result as an update count. - * - * @exception SQLException - * if a database access error occurs - */ - public int getUpdateCount() throws SQLException { - if (this.results == null) { - return -1; - } - - if (this.results.reallyResult()) { - return -1; - } - - int truncatedUpdateCount = 0; - - if (this.results.getUpdateCount() > Integer.MAX_VALUE) { - truncatedUpdateCount = Integer.MAX_VALUE; - } else { - truncatedUpdateCount = (int) this.results.getUpdateCount(); - } - - return truncatedUpdateCount; - } - - /** - * The first warning reported by calls on this Statement is returned. A - * Statement's execute methods clear its java.sql.SQLWarning chain. - * Subsequent Statement warnings will be chained to this - * java.sql.SQLWarning. - * - *

- * The Warning chain is automatically cleared each time a statement is - * (re)executed. - *

- * - *

- * Note: If you are processing a ResultSet then any warnings - * associated with ResultSet reads will be chained on the ResultSet object. - *

- * - * @return the first java.sql.SQLWarning or null - * - * @exception SQLException - * if a database access error occurs - */ - public java.sql.SQLWarning getWarnings() throws SQLException { - checkClosed(); - - if (this.connection != null && !this.connection.isClosed() - && this.connection.versionMeetsMinimum(4, 1, 0)) { - SQLWarning pendingWarningsFromServer = SQLError - .convertShowWarningsToSQLWarnings(this.connection); - - if (this.warningChain != null) { - this.warningChain.setNextWarning(pendingWarningsFromServer); - } else { - this.warningChain = pendingWarningsFromServer; - } - - return this.warningChain; - } - - return this.warningChain; - } - - - - /** - * Closes this statement, and frees resources. - * - * @param calledExplicitly - * was this called from close()? - * - * @throws SQLException - * if an error occurs - */ - protected void realClose(boolean calledExplicitly, boolean closeOpenResults) - throws SQLException { - if (this.isClosed) { - return; - } - - if (this.useUsageAdvisor) { - if (!calledExplicitly) { - String message = Messages.getString("Statement.63") //$NON-NLS-1$ - + Messages.getString("Statement.64"); //$NON-NLS-1$ - - this.eventSink.consumeEvent(new ProfilerEvent( - ProfilerEvent.TYPE_WARN, - "", //$NON-NLS-1$ - this.currentCatalog, this.connectionId, this.getId(), - -1, System.currentTimeMillis(), 0, - Constants.MILLIS_I18N, null, this.pointOfOrigin, - message)); - } - } - - if (this.results != null) { - if (closeOpenResults) { - closeOpenResults = !this.holdResultsOpenOverClose; - } - - if (closeOpenResults && this.connection != null - && !this.connection.getHoldResultsOpenOverStatementClose()) { - try { - this.results.close(); - } catch (Exception ex) { - ; - } - - this.closeAllOpenResults(); - } - } - - if (this.connection != null) { - if (this.maxRowsChanged) { - this.connection.unsetMaxRows(this); - } - - if (!this.connection.getDontTrackOpenResources()) { - this.connection.unregisterStatement(this); - } - } - - this.isClosed = true; - - this.results = null; - this.connection = null; - this.warningChain = null; - this.openResults = null; - this.batchedGeneratedKeys = null; - this.cancelTimeoutMutex = null; - this.pingTarget = null; - } - - /** - * setCursorName defines the SQL cursor name that will be used by subsequent - * execute methods. This name can then be used in SQL positioned - * update/delete statements to identify the current row in the ResultSet - * generated by this statement. If a database doesn't support positioned - * update/delete, this method is a no-op. - * - *

- * Note: This MySQL driver does not support cursors. - *

- * - * @param name - * the new cursor name - * - * @exception SQLException - * if a database access error occurs - */ - public void setCursorName(String name) throws SQLException { - // No-op - } - - /** - * If escape scanning is on (the default), the driver will do escape - * substitution before sending the SQL to the database. - * - * @param enable - * true to enable; false to disable - * - * @exception SQLException - * if a database access error occurs - */ - public void setEscapeProcessing(boolean enable) - throws SQLException { - this.doEscapeProcessing = enable; - } - - /** - * JDBC 2.0 Give a hint as to the direction in which the rows in a result - * set will be processed. The hint applies only to result sets created using - * this Statement object. The default value is ResultSet.FETCH_FORWARD. - * - * @param direction - * the initial direction for processing rows - * - * @exception SQLException - * if a database-access error occurs or direction is not one - * of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or - * ResultSet.FETCH_UNKNOWN - */ - public void setFetchDirection(int direction) throws SQLException { - switch (direction) { - case java.sql.ResultSet.FETCH_FORWARD: - case java.sql.ResultSet.FETCH_REVERSE: - case java.sql.ResultSet.FETCH_UNKNOWN: - break; - - default: - throw SQLError.createSQLException( - Messages.getString("Statement.5"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - } - - /** - * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should - * be fetched from the database when more rows are needed. The number of - * rows specified only affects result sets created using this statement. If - * the value specified is zero, then the hint is ignored. The default value - * is zero. - * - * @param rows - * the number of rows to fetch - * - * @exception SQLException - * if a database-access error occurs, or the condition 0 - * <= rows <= this.getMaxRows() is not satisfied. - */ - public void setFetchSize(int rows) throws SQLException { - if (((rows < 0) && (rows != Integer.MIN_VALUE)) - || ((this.maxRows != 0) && (this.maxRows != -1) && (rows > this - .getMaxRows()))) { - throw SQLError.createSQLException( - Messages.getString("Statement.7"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ - } - - this.fetchSize = rows; - } - - protected void setHoldResultsOpenOverClose(boolean holdResultsOpenOverClose) { - this.holdResultsOpenOverClose = holdResultsOpenOverClose; - } - - /** - * Sets the maxFieldSize - * - * @param max - * the new max column size limit; zero means unlimited - * - * @exception SQLException - * if size exceeds buffer size - */ - public void setMaxFieldSize(int max) throws SQLException { - if (max < 0) { - throw SQLError.createSQLException(Messages - .getString("Statement.11"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - - int maxBuf = (this.connection != null) ? this.connection - .getMaxAllowedPacket() : MysqlIO.getMaxBuf(); - - if (max > maxBuf) { - throw SQLError.createSQLException(Messages.getString( - "Statement.13", //$NON-NLS-1$ - new Object[] { new Long(maxBuf) }), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - - this.maxFieldSize = max; - } - - /** - * Set the maximum number of rows - * - * @param max - * the new max rows limit; zero means unlimited - * - * @exception SQLException - * if a database access error occurs - * - * @see getMaxRows - */ - public void setMaxRows(int max) throws SQLException { - if ((max > MysqlDefs.MAX_ROWS) || (max < 0)) { - throw SQLError - .createSQLException( - Messages.getString("Statement.15") + max //$NON-NLS-1$ - + " > " //$NON-NLS-1$ //$NON-NLS-2$ - + MysqlDefs.MAX_ROWS + ".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ - } - - if (max == 0) { - max = -1; - } - - this.maxRows = max; - this.maxRowsChanged = true; - - if (this.maxRows == -1) { - this.connection.unsetMaxRows(this); - this.maxRowsChanged = false; - } else { - // Most people don't use setMaxRows() - // so don't penalize them - // with the extra query it takes - // to do it efficiently unless we need - // to. - this.connection.maxRowsChanged(this); - } - } - - /** - * Sets the queryTimeout limit - * - * @param seconds - - * the new query timeout limit in seconds - * - * @exception SQLException - * if a database access error occurs - */ - public void setQueryTimeout(int seconds) throws SQLException { - if (seconds < 0) { - throw SQLError.createSQLException(Messages - .getString("Statement.21"), //$NON-NLS-1$ - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ - } - - this.timeoutInMillis = seconds * 1000; - } - - /** - * Sets the concurrency for result sets generated by this statement - * - * @param concurrencyFlag - * DOCUMENT ME! - */ - void setResultSetConcurrency(int concurrencyFlag) { - this.resultSetConcurrency = concurrencyFlag; - } - - /** - * Sets the result set type for result sets generated by this statement - * - * @param typeFlag - * DOCUMENT ME! - */ - void setResultSetType(int typeFlag) { - this.resultSetType = typeFlag; - } - - protected void getBatchedGeneratedKeys(java.sql.Statement batchedStatement) throws SQLException { - if (this.retrieveGeneratedKeys) { - java.sql.ResultSet rs = null; - - try { - rs = batchedStatement.getGeneratedKeys(); - - while (rs.next()) { - this.batchedGeneratedKeys - .add(new byte[][] { rs.getBytes(1) }); - } - } finally { - if (rs != null) { - rs.close(); - } - } - } - } - - protected void getBatchedGeneratedKeys() throws SQLException { - if (this.retrieveGeneratedKeys) { - java.sql.ResultSet rs = null; - - try { - rs = getGeneratedKeysInternal(); - - while (rs.next()) { - this.batchedGeneratedKeys - .add(new byte[][] { rs.getBytes(1) }); - } - } finally { - if (rs != null) { - rs.close(); - } - } - } - } - - /** + * Returns the number of open result sets for this statement. * @return */ - private boolean useServerFetch() throws SQLException { + public abstract int getOpenResultSetCount(); - return this.connection.isCursorFetchEnabled() && this.fetchSize > 0 - && this.resultSetConcurrency == ResultSet.CONCUR_READ_ONLY - && this.resultSetType == ResultSet.TYPE_FORWARD_ONLY; - } - - protected int findStartOfStatement(String sql) { - int statementStartPos = 0; - - if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) { - statementStartPos = sql.indexOf("*/"); - - if (statementStartPos == -1) { - statementStartPos = 0; - } else { - statementStartPos += 2; - } - } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "--") - || StringUtils.startsWithIgnoreCaseAndWs(sql, "#")) { - statementStartPos = sql.indexOf('\n'); - - if (statementStartPos == -1) { - statementStartPos = sql.indexOf('\r'); - - if (statementStartPos == -1) { - statementStartPos = 0; - } - } - } - - return statementStartPos; - } - - protected synchronized void setPingTarget(PingTarget pingTarget) { - this.pingTarget = pingTarget; - } + public void setHoldResultsOpenOverClose(boolean holdResultsOpenOverClose); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementImpl.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementImpl.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementImpl.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,2981 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.io.InputStream; +import java.math.BigInteger; +import java.sql.BatchUpdateException; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Enumeration; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.mysql.jdbc.exceptions.MySQLStatementCancelledException; +import com.mysql.jdbc.exceptions.MySQLTimeoutException; +import com.mysql.jdbc.log.LogUtils; +import com.mysql.jdbc.profiler.ProfilerEvent; +import com.mysql.jdbc.profiler.ProfilerEventHandler; + +/** + * A Statement object is used for executing a static SQL statement and obtaining + * the results produced by it. + * + *

+ * Only one ResultSet per Statement can be open at any point in time. Therefore, + * if the reading of one ResultSet is interleaved with the reading of another, + * each must have been generated by different Statements. All statement execute + * methods implicitly close a statement's current ResultSet if an open one + * exists. + *

+ * + * @author Mark Matthews + * @version $Id: Statement.java 4624 2005-11-28 14:24:29 -0600 (Mon, 28 Nov + * 2005) mmatthews $ + * + * @see java.sql.Statement + * @see ResultSetInternalMethods + */ +public class StatementImpl implements Statement { + protected static final String PING_MARKER = "/* ping */"; + /** + * Thread used to implement query timeouts...Eventually we could be more + * efficient and have one thread with timers, but this is a straightforward + * and simple way to implement a feature that isn't used all that often. + */ + class CancelTask extends TimerTask { + + long connectionId = 0; + String origHost = ""; + SQLException caughtWhileCancelling = null; + StatementImpl toCancel; + Properties origConnProps = null; + String origConnURL = ""; + + CancelTask(StatementImpl cancellee) throws SQLException { + connectionId = cancellee.connectionId; + origHost = connection.getHost(); + toCancel = cancellee; + origConnProps = new Properties(); + + Properties props = connection.getProperties(); + + Enumeration keys = props.propertyNames(); + + while (keys.hasMoreElements()) { + String key = keys.nextElement().toString(); + origConnProps.setProperty(key, props.getProperty(key)); + } + + origConnURL = connection.getURL(); + } + + public void run() { + + Thread cancelThread = new Thread() { + + public void run() { + + Connection cancelConn = null; + java.sql.Statement cancelStmt = null; + + try { + if (connection.getQueryTimeoutKillsConnection()) { + toCancel.wasCancelled = true; + toCancel.wasCancelledByTimeout = true; + connection.realClose(false, false, true, + new MySQLStatementCancelledException(Messages.getString("Statement.ConnectionKilledDueToTimeout"))); + } else { + synchronized (cancelTimeoutMutex) { + if (origConnURL.equals(connection.getURL())) { + //All's fine + cancelConn = connection.duplicate(); + cancelStmt = cancelConn.createStatement(); + cancelStmt.execute("KILL QUERY " + connectionId); + } else { + try { + cancelConn = (Connection) DriverManager.getConnection(origConnURL, origConnProps); + cancelStmt = cancelConn.createStatement(); + cancelStmt.execute("KILL QUERY " + connectionId); + } catch (NullPointerException npe){ + //Log this? "Failed to connect to " + origConnURL + " and KILL query" + } + } + toCancel.wasCancelled = true; + toCancel.wasCancelledByTimeout = true; + } + } + } catch (SQLException sqlEx) { + caughtWhileCancelling = sqlEx; + } catch (NullPointerException npe) { + // Case when connection closed while starting to cancel + // We can't easily synchronize this, because then one thread + // can't cancel() a running query + + // ignore, we shouldn't re-throw this, because the connection's + // already closed, so the statement has been timed out. + } finally { + if (cancelStmt != null) { + try { + cancelStmt.close(); + } catch (SQLException sqlEx) { + throw new RuntimeException(sqlEx.toString()); + } + } + + if (cancelConn != null) { + try { + cancelConn.close(); + } catch (SQLException sqlEx) { + throw new RuntimeException(sqlEx.toString()); + } + } + + toCancel = null; + origConnProps = null; + origConnURL = null; + } + } + }; + + cancelThread.start(); + } + } + + /** Mutex to prevent race between returning query results and noticing + that we're timed-out or cancelled. */ + + protected Object cancelTimeoutMutex = new Object(); + + /** Used to generate IDs when profiling. */ + static int statementCounter = 1; + + public final static byte USES_VARIABLES_FALSE = 0; + + public final static byte USES_VARIABLES_TRUE = 1; + + public final static byte USES_VARIABLES_UNKNOWN = -1; + + protected boolean wasCancelled = false; + protected boolean wasCancelledByTimeout = false; + + /** Holds batched commands */ + protected List batchedArgs; + + /** The character converter to use (if available) */ + protected SingleByteCharsetConverter charConverter = null; + + /** The character encoding to use (if available) */ + protected String charEncoding = null; + + /** The connection that created us */ + protected volatile MySQLConnection connection = null; + + protected long connectionId = 0; + + /** The catalog in use */ + protected String currentCatalog = null; + + /** Should we process escape codes? */ + protected boolean doEscapeProcessing = true; + + /** If we're profiling, where should events go to? */ + protected ProfilerEventHandler eventSink = null; + + /** The number of rows to fetch at a time (currently ignored) */ + private int fetchSize = 0; + + /** Has this statement been closed? */ + protected boolean isClosed = false; + + /** The auto_increment value for the last insert */ + protected long lastInsertId = -1; + + /** The max field size for this statement */ + protected int maxFieldSize = MysqlIO.getMaxBuf(); + + /** + * The maximum number of rows to return for this statement (-1 means _all_ + * rows) + */ + protected int maxRows = -1; + + /** Set of currently-open ResultSets */ + protected Set openResults = new HashSet(); + + /** Are we in pedantic mode? */ + protected boolean pedantic = false; + + /** + * Where this statement was created, only used if profileSql or + * useUsageAdvisor set to true. + */ + protected String pointOfOrigin; + + /** Should we profile? */ + protected boolean profileSQL = false; + + /** The current results */ + protected ResultSetInternalMethods results = null; + + protected ResultSetInternalMethods generatedKeysResults = null; + + /** The concurrency for this result set (updatable or not) */ + protected int resultSetConcurrency = 0; + + /** The type of this result set (scroll sensitive or in-sensitive) */ + protected int resultSetType = 0; + + /** Used to identify this statement when profiling. */ + protected int statementId; + + /** The timeout for a query */ + protected int timeoutInMillis = 0; + + /** The update count for this statement */ + protected long updateCount = -1; + + /** Should we use the usage advisor? */ + protected boolean useUsageAdvisor = false; + + /** The warnings chain. */ + protected SQLWarning warningChain = null; + + /** Has clearWarnings() been called? */ + protected boolean clearWarningsCalled = false; + + /** + * Should this statement hold results open over .close() irregardless of + * connection's setting? + */ + protected boolean holdResultsOpenOverClose = false; + + protected ArrayList batchedGeneratedKeys = null; + + protected boolean retrieveGeneratedKeys = false; + + protected boolean continueBatchOnError = false; + + protected PingTarget pingTarget = null; + + protected boolean useLegacyDatetimeCode; + + private ExceptionInterceptor exceptionInterceptor; + + /** Whether or not the last query was of the form ON DUPLICATE KEY UPDATE */ + protected boolean lastQueryIsOnDupKeyUpdate = false; + + /** Are we currently executing a statement? */ + protected final AtomicBoolean statementExecuting = new AtomicBoolean(false); + + /** Are we currently closing results implicitly (internally)? */ + private boolean isImplicitlyClosingResults = false; + + /** + * Constructor for a Statement. + * + * @param c + * the Connection instantation that creates us + * @param catalog + * the database name in use when we were created + * + * @throws SQLException + * if an error occurs. + */ + public StatementImpl(MySQLConnection c, String catalog) throws SQLException { + if ((c == null) || c.isClosed()) { + throw SQLError.createSQLException( + Messages.getString("Statement.0"), //$NON-NLS-1$ + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, null); //$NON-NLS-1$ //$NON-NLS-2$ + } + + this.connection = c; + this.connectionId = this.connection.getId(); + this.exceptionInterceptor = this.connection + .getExceptionInterceptor(); + + this.currentCatalog = catalog; + this.pedantic = this.connection.getPedantic(); + this.continueBatchOnError = this.connection.getContinueBatchOnError(); + this.useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode(); + + if (!this.connection.getDontTrackOpenResources()) { + this.connection.registerStatement(this); + } + + // + // Adjust, if we know it + // + + if (this.connection != null) { + this.maxFieldSize = this.connection.getMaxAllowedPacket(); + + int defaultFetchSize = this.connection.getDefaultFetchSize(); + + if (defaultFetchSize != 0) { + setFetchSize(defaultFetchSize); + } + + if (this.connection.getUseUnicode()) { + this.charEncoding = this.connection.getEncoding(); + + this.charConverter = this.connection.getCharsetConverter(this.charEncoding); + } + + + + boolean profiling = this.connection.getProfileSql() + || this.connection.getUseUsageAdvisor() || this.connection.getLogSlowQueries(); + + if (this.connection.getAutoGenerateTestcaseScript() || profiling) { + this.statementId = statementCounter++; + } + + if (profiling) { + this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable()); + this.profileSQL = this.connection.getProfileSql(); + this.useUsageAdvisor = this.connection.getUseUsageAdvisor(); + this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); + } + + int maxRowsConn = this.connection.getMaxRows(); + + if (maxRowsConn != -1) { + setMaxRows(maxRowsConn); + } + + this.holdResultsOpenOverClose = this.connection.getHoldResultsOpenOverStatementClose(); + } + + version5013OrNewer = this.connection.versionMeetsMinimum(5, 0, 13); + } + + /** + * DOCUMENT ME! + * + * @param sql + * DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public void addBatch(String sql) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.batchedArgs == null) { + this.batchedArgs = new ArrayList(); + } + + if (sql != null) { + this.batchedArgs.add(sql); + } + } + } + + /** Get the batched args as added by the addBatch method(s). + * The list is unmodifiable and might contain any combination of String, + * BatchParams, or BatchedBindValues depending on how the parameters were + * batched. + * @return an unmodifiable List of batched args + */ + public List getBatchedArgs() { + return batchedArgs==null?null:Collections.unmodifiableList(batchedArgs); + } + + /** + * Cancels this Statement object if both the DBMS and driver support + * aborting an SQL statement. This method can be used by one thread to + * cancel a statement that is being executed by another thread. + */ + public void cancel() throws SQLException { + if (!this.statementExecuting.get()) { + return; + } + + if (!this.isClosed && + this.connection != null && + this.connection.versionMeetsMinimum(5, 0, 0)) { + Connection cancelConn = null; + java.sql.Statement cancelStmt = null; + + try { + cancelConn = this.connection.duplicate(); + cancelStmt = cancelConn.createStatement(); + cancelStmt.execute("KILL QUERY " + + this.connection.getIO().getThreadId()); + this.wasCancelled = true; + } finally { + if (cancelStmt != null) { + cancelStmt.close(); + } + + if (cancelConn != null) { + cancelConn.close(); + } + } + + } + } + + // --------------------------JDBC 2.0----------------------------- + + /** + * Checks if closed() has been called, and throws an exception if so + * + * @throws SQLException + * if this statement has been closed + */ + protected MySQLConnection checkClosed() throws SQLException { + MySQLConnection c = this.connection; + + if (c == null) { + throw SQLError.createSQLException(Messages + .getString("Statement.49"), //$NON-NLS-1$ + SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor()); //$NON-NLS-1$ + } + + return c; + } + + /** + * Checks if the given SQL query with the given first non-ws char is a DML + * statement. Throws an exception if it is. + * + * @param sql + * the SQL to check + * @param firstStatementChar + * the UC first non-ws char of the statement + * + * @throws SQLException + * if the statement contains DML + */ + protected void checkForDml(String sql, char firstStatementChar) + throws SQLException { + if ((firstStatementChar == 'I') || (firstStatementChar == 'U') + || (firstStatementChar == 'D') || (firstStatementChar == 'A') + || (firstStatementChar == 'C') || (firstStatementChar == 'T') + || (firstStatementChar == 'R')) { + String noCommentSql = StringUtils.stripComments(sql, + "'\"", "'\"", true, false, true, true); + + if (StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "INSERT") //$NON-NLS-1$ + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "UPDATE") //$NON-NLS-1$ + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DELETE") //$NON-NLS-1$ + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DROP") //$NON-NLS-1$ + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "CREATE") //$NON-NLS-1$ + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "ALTER") + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "TRUNCATE") + || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "RENAME") + ) { //$NON-NLS-1$ + throw SQLError.createSQLException(Messages + .getString("Statement.57"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + } + + /** + * Method checkNullOrEmptyQuery. + * + * @param sql + * the SQL to check + * + * @throws SQLException + * if query is null or empty. + */ + protected void checkNullOrEmptyQuery(String sql) throws SQLException { + if (sql == null) { + throw SQLError.createSQLException(Messages + .getString("Statement.59"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (sql.length() == 0) { + throw SQLError.createSQLException(Messages + .getString("Statement.61"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + /** + * JDBC 2.0 Make the set of commands in the current batch empty. This method + * is optional. + * + * @exception SQLException + * if a database-access error occurs, or the driver does not + * support batch statements + */ + public void clearBatch() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.batchedArgs != null) { + this.batchedArgs.clear(); + } + } + } + + /** + * After this call, getWarnings returns null until a new warning is reported + * for this Statement. + * + * @exception SQLException + * if a database access error occurs (why?) + */ + public void clearWarnings() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.clearWarningsCalled = true; + this.warningChain = null; + } + } + + /** + * In many cases, it is desirable to immediately release a Statement's + * database and JDBC resources instead of waiting for this to happen when it + * is automatically closed. The close method provides this immediate + * release. + * + *

+ * Note: A Statement is automatically closed when it is garbage + * collected. When a Statement is closed, its current ResultSet, if one + * exists, is also closed. + *

+ * + * @exception SQLException + * if a database access error occurs + */ + public void close() throws SQLException { + realClose(true, true); + } + + /** + * Close any open result sets that have been 'held open' + */ + protected void closeAllOpenResults() throws SQLException { + MySQLConnection locallyScopedConn = this.connection; + + if (locallyScopedConn == null) return; // already closed + + synchronized (locallyScopedConn.getConnectionMutex()) { + if (this.openResults != null) { + for (ResultSetInternalMethods element : this.openResults) { + try { + element.realClose(false); + } catch (SQLException sqlEx) { + AssertionFailedException.shouldNotHappen(sqlEx); + } + } + + this.openResults.clear(); + } + } + } + + /** + * Close all result sets in this statement. This includes multi-results + */ + protected void implicitlyCloseAllOpenResults() throws SQLException { + this.isImplicitlyClosingResults = true; + try { + if (!(connection.getHoldResultsOpenOverStatementClose() || + connection.getDontTrackOpenResources() || + this.holdResultsOpenOverClose)) { + if (this.results != null) { + this.results.realClose(false); + } + if (this.generatedKeysResults != null) { + this.generatedKeysResults.realClose(false); + } + closeAllOpenResults(); + } + } finally { + this.isImplicitlyClosingResults = false; + } + } + + public void removeOpenResultSet(ResultSetInternalMethods rs) { + try { + synchronized (checkClosed().getConnectionMutex()) { + if (this.openResults != null) { + this.openResults.remove(rs); + } + + boolean hasMoreResults = rs.getNextResultSet() != null; + + // clear the current results or GGK results + if (this.results == rs && !hasMoreResults) { + this.results = null; + } + if (this.generatedKeysResults == rs) { + this.generatedKeysResults = null; + } + + // trigger closeOnCompletion if: + // a) the result set removal wasn't triggered internally + // b) there are no additional results + if (!this.isImplicitlyClosingResults && !hasMoreResults) { + checkAndPerformCloseOnCompletionAction(); + } + } + } catch (SQLException e) { + // we can't break the interface, having this be no-op in case of error is ok + } + } + + public int getOpenResultSetCount() { + try { + synchronized (checkClosed().getConnectionMutex()) { + if (this.openResults != null) { + return this.openResults.size(); + } + + return 0; + } + } catch (SQLException e) { + // we can't break the interface, having this be no-op in case of error is ok + + return 0; + } + } + + /** + * Check if all ResultSets generated by this statement are closed. If so, + * close this statement. + */ + private void checkAndPerformCloseOnCompletionAction() { + try { + synchronized (checkClosed().getConnectionMutex()) { + if (isCloseOnCompletion() + && !connection.getDontTrackOpenResources() + && getOpenResultSetCount() == 0 + && (this.results == null || !this.results.reallyResult() || this.results.isClosed()) + && (this.generatedKeysResults == null || + !this.generatedKeysResults.reallyResult() || + this.generatedKeysResults.isClosed())) { + realClose(false, false); + } + } + } catch (SQLException e) { + } + } + + /** + * @param sql + * @return + */ + private ResultSetInternalMethods createResultSetUsingServerFetch(String sql) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + java.sql.PreparedStatement pStmt = this.connection.prepareStatement( + sql, this.resultSetType, this.resultSetConcurrency); + + pStmt.setFetchSize(this.fetchSize); + + if (this.maxRows > -1) { + pStmt.setMaxRows(this.maxRows); + } + + statementBegins(); + + pStmt.execute(); + + // + // Need to be able to get resultset irrespective if we issued DML or + // not to make this work. + // + ResultSetInternalMethods rs = ((com.mysql.jdbc.StatementImpl) pStmt) + .getResultSetInternal(); + + rs + .setStatementUsedForFetchingRows((com.mysql.jdbc.PreparedStatement) pStmt); + + this.results = rs; + + return rs; + } + } + + /** + * We only stream result sets when they are forward-only, read-only, and the + * fetch size has been set to Integer.MIN_VALUE + * + * @return true if this result set should be streamed row at-a-time, rather + * than read all at once. + */ + protected boolean createStreamingResultSet() { + try { + synchronized (checkClosed().getConnectionMutex()) { + return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY) + && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) && (this.fetchSize == Integer.MIN_VALUE)); + } + } catch (SQLException e) { + // we can't break the interface, having this be no-op in case of error is ok + + return false; + } + } + + private int originalResultSetType = 0; + private int originalFetchSize = 0; + + /* (non-Javadoc) + * @see com.mysql.jdbc.IStatement#enableStreamingResults() + */ + public void enableStreamingResults() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.originalResultSetType = this.resultSetType; + this.originalFetchSize = this.fetchSize; + + setFetchSize(Integer.MIN_VALUE); + setResultSetType(ResultSet.TYPE_FORWARD_ONLY); + } + } + + public void disableStreamingResults() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.fetchSize == Integer.MIN_VALUE && + this.resultSetType == ResultSet.TYPE_FORWARD_ONLY) { + setFetchSize(this.originalFetchSize); + setResultSetType(this.originalResultSetType); + } + } + } + + /** + * Execute a SQL statement that may return multiple results. We don't have + * to worry about this since we do not support multiple ResultSets. You can + * use getResultSet or getUpdateCount to retrieve the result. + * + * @param sql + * any SQL statement + * + * @return true if the next result is a ResulSet, false if it is an update + * count or there are no more results + * + * @exception SQLException + * if a database access error occurs + */ + public boolean execute(String sql) throws SQLException { + return execute(sql, false); + } + + private boolean execute(String sql, boolean returnGeneratedKeys) throws SQLException { + MySQLConnection locallyScopedConn = checkClosed(); + + synchronized (locallyScopedConn.getConnectionMutex()) { + this.retrieveGeneratedKeys = returnGeneratedKeys; + lastQueryIsOnDupKeyUpdate = false; + if (returnGeneratedKeys) + lastQueryIsOnDupKeyUpdate = containsOnDuplicateKeyInString(sql); + + resetCancelledState(); + + checkNullOrEmptyQuery(sql); + + checkClosed(); + + char firstNonWsChar = StringUtils.firstAlphaCharUc(sql, findStartOfStatement(sql)); + + boolean isSelect = true; + + if (firstNonWsChar != 'S') { + isSelect = false; + + if (locallyScopedConn.isReadOnly()) { + throw SQLError.createSQLException(Messages + .getString("Statement.27") //$NON-NLS-1$ + + Messages.getString("Statement.28"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + boolean doStreaming = createStreamingResultSet(); + + try { + // Adjust net_write_timeout to a higher value if we're + // streaming result sets. More often than not, someone runs into + // an issue where they blow net_write_timeout when using this + // feature, and if they're willing to hold a result set open + // for 30 seconds or more, one more round-trip isn't going to hurt + // + // This is reset by RowDataDynamic.close(). + + if (doStreaming + && locallyScopedConn.getNetTimeoutForStreamingResults() > 0) { + executeSimpleNonQuery(locallyScopedConn, "SET net_write_timeout=" + + locallyScopedConn.getNetTimeoutForStreamingResults()); + } + + if (this.doEscapeProcessing) { + Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, + locallyScopedConn.serverSupportsConvertFn(), locallyScopedConn); + + if (escapedSqlResult instanceof String) { + sql = (String) escapedSqlResult; + } else { + sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; + } + } + + implicitlyCloseAllOpenResults(); + + if (sql.charAt(0) == '/') { + if (sql.startsWith(PING_MARKER)) { + doPingInstead(); + + return true; + } + } + + CachedResultSetMetaData cachedMetaData = null; + + ResultSetInternalMethods rs = null; + + this.batchedGeneratedKeys = null; + + if (useServerFetch()) { + rs = createResultSetUsingServerFetch(sql); + } else { + CancelTask timeoutTask = null; + + String oldCatalog = null; + + try { + if (locallyScopedConn.getEnableQueryTimeouts() && + this.timeoutInMillis != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + this.timeoutInMillis); + } + + if (!locallyScopedConn.getCatalog().equals( + this.currentCatalog)) { + oldCatalog = locallyScopedConn.getCatalog(); + locallyScopedConn.setCatalog(this.currentCatalog); + } + + // + // Check if we have cached metadata for this query... + // + + Field[] cachedFields = null; + + if (locallyScopedConn.getCacheResultSetMetadata()) { + cachedMetaData = locallyScopedConn.getCachedMetaData(sql); + + if (cachedMetaData != null) { + cachedFields = cachedMetaData.fields; + } + } + + // + // Only apply max_rows to selects + // + locallyScopedConn.setSessionMaxRows(isSelect ? this.maxRows : -1); + + statementBegins(); + + rs = locallyScopedConn.execSQL(this, sql, this.maxRows, null, this.resultSetType, + this.resultSetConcurrency, doStreaming, this.currentCatalog, cachedFields); + + if (timeoutTask != null) { + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } + + timeoutTask.cancel(); + timeoutTask = null; + } + + synchronized (this.cancelTimeoutMutex) { + if (this.wasCancelled) { + SQLException cause = null; + + if (this.wasCancelledByTimeout) { + cause = new MySQLTimeoutException(); + } else { + cause = new MySQLStatementCancelledException(); + } + + resetCancelledState(); + + throw cause; + } + } + } finally { + if (timeoutTask != null) { + timeoutTask.cancel(); + locallyScopedConn.getCancelTimer().purge(); + } + + if (oldCatalog != null) { + locallyScopedConn.setCatalog(oldCatalog); + } + } + } + + if (rs != null) { + this.lastInsertId = rs.getUpdateID(); + + this.results = rs; + + rs.setFirstCharOfQuery(firstNonWsChar); + + if (rs.reallyResult()) { + if (cachedMetaData != null) { + locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData, + this.results); + } else { + if (this.connection.getCacheResultSetMetadata()) { + locallyScopedConn.initializeResultsMetadataFromCache(sql, + null /* will be created */, this.results); + } + } + } + } + + return ((rs != null) && rs.reallyResult()); + } finally { + this.statementExecuting.set(false); + } + } + } + + protected void statementBegins() { + this.clearWarningsCalled = false; + this.statementExecuting.set(true); + } + + protected void resetCancelledState() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.cancelTimeoutMutex == null) { + return; + } + + synchronized (this.cancelTimeoutMutex) { + this.wasCancelled = false; + this.wasCancelledByTimeout = false; + } + } + } + + /** + * @see StatementImpl#execute(String, int) + */ + public boolean execute(String sql, int returnGeneratedKeys) + throws SQLException { + + + if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) { + checkClosed(); + + MySQLConnection locallyScopedConn = this.connection; + + synchronized (locallyScopedConn.getConnectionMutex()) { + // If this is a 'REPLACE' query, we need to be able to parse + // the 'info' message returned from the server to determine + // the actual number of keys generated. + boolean readInfoMsgState = this.connection + .isReadInfoMsgEnabled(); + locallyScopedConn.setReadInfoMsgEnabled(true); + + try { + return execute(sql, true); + } finally { + locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); + } + } + } + + return execute(sql); + } + + /** + * @see StatementImpl#execute(String, int[]) + */ + public boolean execute(String sql, int[] generatedKeyIndices) + throws SQLException { + MySQLConnection locallyScopedConn = checkClosed(); + + synchronized (locallyScopedConn.getConnectionMutex()) { + if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) { + + this.retrieveGeneratedKeys = true; + + // If this is a 'REPLACE' query, we need to be able to parse + // the 'info' message returned from the server to determine + // the actual number of keys generated. + boolean readInfoMsgState = locallyScopedConn + .isReadInfoMsgEnabled(); + locallyScopedConn.setReadInfoMsgEnabled(true); + + try { + return execute(sql, true); + } finally { + locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); + } + } + + return execute(sql); + } + } + + /** + * @see StatementImpl#execute(String, String[]) + */ + public boolean execute(String sql, String[] generatedKeyNames) + throws SQLException { + MySQLConnection locallyScopedConn = checkClosed(); + + synchronized (locallyScopedConn.getConnectionMutex()) { + if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) { + + this.retrieveGeneratedKeys = true; + // If this is a 'REPLACE' query, we need to be able to parse + // the 'info' message returned from the server to determine + // the actual number of keys generated. + boolean readInfoMsgState = this.connection + .isReadInfoMsgEnabled(); + locallyScopedConn.setReadInfoMsgEnabled(true); + + try { + return execute(sql, true); + } finally { + locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); + } + } + + return execute(sql); + } + } + + /** + * JDBC 2.0 Submit a batch of commands to the database for execution. This + * method is optional. + * + * @return an array of update counts containing one element for each command + * in the batch. The array is ordered according to the order in + * which commands were inserted into the batch + * + * @exception SQLException + * if a database-access error occurs, or the driver does not + * support batch statements + * @throws java.sql.BatchUpdateException + * DOCUMENT ME! + */ + public int[] executeBatch() throws SQLException { + MySQLConnection locallyScopedConn = checkClosed(); + + synchronized (locallyScopedConn.getConnectionMutex()) { + if (locallyScopedConn.isReadOnly()) { + throw SQLError.createSQLException(Messages + .getString("Statement.34") //$NON-NLS-1$ + + Messages.getString("Statement.35"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + implicitlyCloseAllOpenResults(); + + if (this.batchedArgs == null || this.batchedArgs.size() == 0) { + return new int[0]; + } + + // we timeout the entire batch, not individual statements + int individualStatementTimeout = this.timeoutInMillis; + this.timeoutInMillis = 0; + + CancelTask timeoutTask = null; + + try { + resetCancelledState(); + + statementBegins(); + + try { + this.retrieveGeneratedKeys = true; // The JDBC spec doesn't forbid this, but doesn't provide for it either...we do.. + + int[] updateCounts = null; + + + if (this.batchedArgs != null) { + int nbrCommands = this.batchedArgs.size(); + + this.batchedGeneratedKeys = new ArrayList(this.batchedArgs.size()); + + boolean multiQueriesEnabled = locallyScopedConn.getAllowMultiQueries(); + + if (locallyScopedConn.versionMeetsMinimum(4, 1, 1) && + (multiQueriesEnabled || + (locallyScopedConn.getRewriteBatchedStatements() && + nbrCommands > 4))) { + return executeBatchUsingMultiQueries(multiQueriesEnabled, nbrCommands, individualStatementTimeout); + } + + if (locallyScopedConn.getEnableQueryTimeouts() && + individualStatementTimeout != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + individualStatementTimeout); + } + + updateCounts = new int[nbrCommands]; + + for (int i = 0; i < nbrCommands; i++) { + updateCounts[i] = -3; + } + + SQLException sqlEx = null; + + int commandIndex = 0; + + for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { + try { + String sql = (String) this.batchedArgs.get(commandIndex); + updateCounts[commandIndex] = executeUpdate(sql, true, true); + // limit one generated key per OnDuplicateKey statement + getBatchedGeneratedKeys(containsOnDuplicateKeyInString(sql) ? 1 : 0); + } catch (SQLException ex) { + updateCounts[commandIndex] = EXECUTE_FAILED; + + if (this.continueBatchOnError && + !(ex instanceof MySQLTimeoutException) && + !(ex instanceof MySQLStatementCancelledException) && + !hasDeadlockOrTimeoutRolledBackTx(ex)) { + sqlEx = ex; + } else { + int[] newUpdateCounts = new int[commandIndex]; + + if (hasDeadlockOrTimeoutRolledBackTx(ex)) { + for (int i = 0; i < newUpdateCounts.length; i++) { + newUpdateCounts[i] = Statement.EXECUTE_FAILED; + } + } else { + System.arraycopy(updateCounts, 0, + newUpdateCounts, 0, commandIndex); + } + + throw new java.sql.BatchUpdateException(ex + .getMessage(), ex.getSQLState(), ex + .getErrorCode(), newUpdateCounts); + } + } + } + + if (sqlEx != null) { + throw new java.sql.BatchUpdateException(sqlEx + .getMessage(), sqlEx.getSQLState(), sqlEx + .getErrorCode(), updateCounts); + } + } + + if (timeoutTask != null) { + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } + + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + timeoutTask = null; + } + + return (updateCounts != null) ? updateCounts : new int[0]; + } finally { + this.statementExecuting.set(false); + } + } finally { + + if (timeoutTask != null) { + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + } + + resetCancelledState(); + + this.timeoutInMillis = individualStatementTimeout; + + clearBatch(); + } + } + } + + protected final boolean hasDeadlockOrTimeoutRolledBackTx(SQLException ex) { + int vendorCode = ex.getErrorCode(); + + switch (vendorCode) { + case MysqlErrorNumbers.ER_LOCK_DEADLOCK: + case MysqlErrorNumbers.ER_LOCK_TABLE_FULL: + return true; + case MysqlErrorNumbers.ER_LOCK_WAIT_TIMEOUT: + return !version5013OrNewer; + default: + return false; + } + } + + /** + * Rewrites batch into a single query to send to the server. This method + * will constrain each batch to be shorter than max_allowed_packet on the + * server. + * + * @return update counts in the same manner as executeBatch() + * @throws SQLException + */ + private int[] executeBatchUsingMultiQueries(boolean multiQueriesEnabled, + int nbrCommands, int individualStatementTimeout) throws SQLException { + + MySQLConnection locallyScopedConn = checkClosed(); + + synchronized (locallyScopedConn.getConnectionMutex()) { + if (!multiQueriesEnabled) { + locallyScopedConn.getIO().enableMultiQueries(); + } + + java.sql.Statement batchStmt = null; + + CancelTask timeoutTask = null; + + try { + int[] updateCounts = new int[nbrCommands]; + + for (int i = 0; i < nbrCommands; i++) { + updateCounts[i] = -3; + } + + int commandIndex = 0; + + StringBuffer queryBuf = new StringBuffer(); + + batchStmt = locallyScopedConn.createStatement(); + + if (locallyScopedConn.getEnableQueryTimeouts() && + individualStatementTimeout != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask((StatementImpl)batchStmt); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + individualStatementTimeout); + } + + int counter = 0; + + int numberOfBytesPerChar = 1; + + String connectionEncoding = locallyScopedConn.getEncoding(); + + if (StringUtils.startsWithIgnoreCase(connectionEncoding, "utf")) { + numberOfBytesPerChar = 3; + } else if (CharsetMapping.isMultibyteCharset(connectionEncoding)) { + numberOfBytesPerChar = 2; + } + + int escapeAdjust = 1; + + batchStmt.setEscapeProcessing(this.doEscapeProcessing); + + if (this.doEscapeProcessing) { + + escapeAdjust = 2; /* We assume packet _could_ grow by this amount, as we're not + sure how big statement will end up after + escape processing */ + } + + SQLException sqlEx = null; + + int argumentSetsInBatchSoFar = 0; + + for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) { + String nextQuery = (String) this.batchedArgs.get(commandIndex); + + if (((((queryBuf.length() + nextQuery.length()) + * numberOfBytesPerChar) + 1 /* for semicolon */ + + MysqlIO.HEADER_LENGTH) * escapeAdjust) + 32 > this.connection + .getMaxAllowedPacket()) { + try { + batchStmt.execute(queryBuf.toString(), Statement.RETURN_GENERATED_KEYS); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(commandIndex, + argumentSetsInBatchSoFar, updateCounts, ex); + } + + counter = processMultiCountsAndKeys((StatementImpl)batchStmt, counter, + updateCounts); + + queryBuf = new StringBuffer(); + argumentSetsInBatchSoFar = 0; + } + + queryBuf.append(nextQuery); + queryBuf.append(";"); + argumentSetsInBatchSoFar++; + } + + if (queryBuf.length() > 0) { + try { + batchStmt.execute(queryBuf.toString(), Statement.RETURN_GENERATED_KEYS); + } catch (SQLException ex) { + sqlEx = handleExceptionForBatch(commandIndex - 1, + argumentSetsInBatchSoFar, updateCounts, ex); + } + + counter = processMultiCountsAndKeys((StatementImpl)batchStmt, counter, + updateCounts); + } + + if (timeoutTask != null) { + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } + + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + + timeoutTask = null; + } + + if (sqlEx != null) { + throw new java.sql.BatchUpdateException(sqlEx + .getMessage(), sqlEx.getSQLState(), sqlEx + .getErrorCode(), updateCounts); + } + + return (updateCounts != null) ? updateCounts : new int[0]; + } finally { + if (timeoutTask != null) { + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + } + + resetCancelledState(); + + try { + if (batchStmt != null) { + batchStmt.close(); + } + } finally { + if (!multiQueriesEnabled) { + locallyScopedConn.getIO().disableMultiQueries(); + } + } + } + } + } + + protected int processMultiCountsAndKeys( + StatementImpl batchedStatement, + int updateCountCounter, int[] updateCounts) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + updateCounts[updateCountCounter++] = batchedStatement.getUpdateCount(); + + boolean doGenKeys = this.batchedGeneratedKeys != null; + + byte[][] row = null; + + if (doGenKeys) { + long generatedKey = batchedStatement.getLastInsertID(); + + row = new byte[1][]; + row[0] = StringUtils.getBytes(Long.toString(generatedKey)); + this.batchedGeneratedKeys.add(new ByteArrayRow(row, getExceptionInterceptor())); + } + + while (batchedStatement.getMoreResults() + || batchedStatement.getUpdateCount() != -1) { + updateCounts[updateCountCounter++] = batchedStatement.getUpdateCount(); + + if (doGenKeys) { + long generatedKey = batchedStatement.getLastInsertID(); + + row = new byte[1][]; + row[0] = StringUtils.getBytes(Long.toString(generatedKey)); + this.batchedGeneratedKeys.add(new ByteArrayRow(row, getExceptionInterceptor())); + } + } + + return updateCountCounter; + } + } + + protected SQLException handleExceptionForBatch(int endOfBatchIndex, + int numValuesPerBatch, int[] updateCounts, SQLException ex) + throws BatchUpdateException { + SQLException sqlEx; + + for (int j = endOfBatchIndex; j > endOfBatchIndex - numValuesPerBatch; j--) { + updateCounts[j] = EXECUTE_FAILED; + } + + if (this.continueBatchOnError && + !(ex instanceof MySQLTimeoutException) && + !(ex instanceof MySQLStatementCancelledException) && + !hasDeadlockOrTimeoutRolledBackTx(ex)) { + sqlEx = ex; + } else { + int[] newUpdateCounts = new int[endOfBatchIndex]; + System.arraycopy(updateCounts, 0, + newUpdateCounts, 0, endOfBatchIndex); + + BatchUpdateException batchException = new BatchUpdateException(ex + .getMessage(), ex.getSQLState(), ex + .getErrorCode(), newUpdateCounts); + batchException.initCause(ex); + throw batchException; + } + + return sqlEx; + } + + /** + * Execute a SQL statement that returns a single ResultSet + * + * @param sql + * typically a static SQL SELECT statement + * + * @return a ResulSet that contains the data produced by the query + * + * @exception SQLException + * if a database access error occurs + */ + public java.sql.ResultSet executeQuery(String sql) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + MySQLConnection locallyScopedConn = this.connection; + + this.retrieveGeneratedKeys = false; + + resetCancelledState(); + + checkNullOrEmptyQuery(sql); + + boolean doStreaming = createStreamingResultSet(); + + // Adjust net_write_timeout to a higher value if we're + // streaming result sets. More often than not, someone runs into + // an issue where they blow net_write_timeout when using this + // feature, and if they're willing to hold a result set open + // for 30 seconds or more, one more round-trip isn't going to hurt + // + // This is reset by RowDataDynamic.close(). + + if (doStreaming + && this.connection.getNetTimeoutForStreamingResults() > 0) { + executeSimpleNonQuery(locallyScopedConn, "SET net_write_timeout=" + + this.connection.getNetTimeoutForStreamingResults()); + } + + if (this.doEscapeProcessing) { + Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, + locallyScopedConn.serverSupportsConvertFn(), this.connection); + + if (escapedSqlResult instanceof String) { + sql = (String) escapedSqlResult; + } else { + sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; + } + } + + char firstStatementChar = StringUtils.firstNonWsCharUc(sql, + findStartOfStatement(sql)); + + if (sql.charAt(0) == '/') { + if (sql.startsWith(PING_MARKER)) { + doPingInstead(); + + return this.results; + } + } + + checkForDml(sql, firstStatementChar); + + implicitlyCloseAllOpenResults(); + + CachedResultSetMetaData cachedMetaData = null; + + if (useServerFetch()) { + this.results = createResultSetUsingServerFetch(sql); + + return this.results; + } + + CancelTask timeoutTask = null; + + String oldCatalog = null; + + try { + if (locallyScopedConn.getEnableQueryTimeouts() && + this.timeoutInMillis != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + this.timeoutInMillis); + } + + if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) { + oldCatalog = locallyScopedConn.getCatalog(); + locallyScopedConn.setCatalog(this.currentCatalog); + } + + // + // Check if we have cached metadata for this query... + // + + Field[] cachedFields = null; + + if (locallyScopedConn.getCacheResultSetMetadata()) { + cachedMetaData = locallyScopedConn.getCachedMetaData(sql); + + if (cachedMetaData != null) { + cachedFields = cachedMetaData.fields; + } + } + + locallyScopedConn.setSessionMaxRows(this.maxRows); + + statementBegins(); + + this.results = locallyScopedConn.execSQL(this, sql, this.maxRows, null, + this.resultSetType, this.resultSetConcurrency, doStreaming, this.currentCatalog, cachedFields); + + if (timeoutTask != null) { + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } + + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + + timeoutTask = null; + } + + synchronized (this.cancelTimeoutMutex) { + if (this.wasCancelled) { + SQLException cause = null; + + if (this.wasCancelledByTimeout) { + cause = new MySQLTimeoutException(); + } else { + cause = new MySQLStatementCancelledException(); + } + + resetCancelledState(); + + throw cause; + } + } + } finally { + this.statementExecuting.set(false); + + if (timeoutTask != null) { + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + } + + if (oldCatalog != null) { + locallyScopedConn.setCatalog(oldCatalog); + } + } + + this.lastInsertId = this.results.getUpdateID(); + + if (cachedMetaData != null) { + locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData, + this.results); + } else { + if (this.connection.getCacheResultSetMetadata()) { + locallyScopedConn.initializeResultsMetadataFromCache(sql, + null /* will be created */, this.results); + } + } + + return this.results; + } + } + + protected void doPingInstead() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.pingTarget != null) { + this.pingTarget.doPing(); + } else { + this.connection.ping(); + } + + ResultSetInternalMethods fakeSelectOneResultSet = generatePingResultSet(); + this.results = fakeSelectOneResultSet; + } + } + + protected ResultSetInternalMethods generatePingResultSet() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + Field[] fields = { new Field(null, "1", Types.BIGINT, 1) }; + ArrayList rows = new ArrayList(); + byte[] colVal = new byte[] { (byte) '1' }; + + rows.add(new ByteArrayRow(new byte[][] { colVal }, getExceptionInterceptor())); + + return (ResultSetInternalMethods) DatabaseMetaData.buildResultSet(fields, rows, + this.connection); + } + } + + protected void executeSimpleNonQuery(MySQLConnection c, String nonQuery) + throws SQLException { + c.execSQL(this, nonQuery, + -1, null, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY, false, this.currentCatalog, + null, false).close(); + } + + /** + * Execute a SQL INSERT, UPDATE or DELETE statement. In addition SQL + * statements that return nothing such as SQL DDL statements can be executed + * Any IDs generated for AUTO_INCREMENT fields can be retrieved by casting + * this Statement to org.gjt.mm.mysql.Statement and calling the + * getLastInsertID() method. + * + * @param sql + * a SQL statement + * + * @return either a row count, or 0 for SQL commands + * + * @exception SQLException + * if a database access error occurs + */ + public int executeUpdate(String sql) throws SQLException { + return executeUpdate(sql, false, false); + } + + protected int executeUpdate(String sql, boolean isBatch, boolean returnGeneratedKeys) + throws SQLException { + + synchronized (checkClosed().getConnectionMutex()) { + MySQLConnection locallyScopedConn = this.connection; + + char firstStatementChar = StringUtils.firstAlphaCharUc(sql, + findStartOfStatement(sql)); + + ResultSetInternalMethods rs = null; + + this.retrieveGeneratedKeys = returnGeneratedKeys; + + resetCancelledState(); + + checkNullOrEmptyQuery(sql); + + if (this.doEscapeProcessing) { + Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, + this.connection.serverSupportsConvertFn(), this.connection); + + if (escapedSqlResult instanceof String) { + sql = (String) escapedSqlResult; + } else { + sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql; + } + } + + if (locallyScopedConn.isReadOnly(false)) { + throw SQLError.createSQLException(Messages + .getString("Statement.42") //$NON-NLS-1$ + + Messages.getString("Statement.43"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + if (StringUtils.startsWithIgnoreCaseAndWs(sql, "select")) { //$NON-NLS-1$ + throw SQLError.createSQLException(Messages + .getString("Statement.46"), //$NON-NLS-1$ + "01S03", getExceptionInterceptor()); //$NON-NLS-1$ + } + + implicitlyCloseAllOpenResults(); + + // The checking and changing of catalogs + // must happen in sequence, so synchronize + // on the same mutex that _conn is using + + CancelTask timeoutTask = null; + + String oldCatalog = null; + + try { + if (locallyScopedConn.getEnableQueryTimeouts() && + this.timeoutInMillis != 0 + && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) { + timeoutTask = new CancelTask(this); + locallyScopedConn.getCancelTimer().schedule(timeoutTask, + this.timeoutInMillis); + } + + if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) { + oldCatalog = locallyScopedConn.getCatalog(); + locallyScopedConn.setCatalog(this.currentCatalog); + } + + // + // Only apply max_rows to selects + // + locallyScopedConn.setSessionMaxRows(-1); + + statementBegins(); + + // null catalog: force read of field info on DML + rs = locallyScopedConn.execSQL(this, sql, -1, null, + java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, false, + this.currentCatalog, null, isBatch); + + if (timeoutTask != null) { + if (timeoutTask.caughtWhileCancelling != null) { + throw timeoutTask.caughtWhileCancelling; + } + + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + + timeoutTask = null; + } + + synchronized (this.cancelTimeoutMutex) { + if (this.wasCancelled) { + SQLException cause = null; + + if (this.wasCancelledByTimeout) { + cause = new MySQLTimeoutException(); + } else { + cause = new MySQLStatementCancelledException(); + } + + resetCancelledState(); + + throw cause; + } + } + } finally { + if (timeoutTask != null) { + timeoutTask.cancel(); + + locallyScopedConn.getCancelTimer().purge(); + } + + if (oldCatalog != null) { + locallyScopedConn.setCatalog(oldCatalog); + } + + if (!isBatch) { + this.statementExecuting.set(false); + } + } + + this.results = rs; + + rs.setFirstCharOfQuery(firstStatementChar); + + this.updateCount = rs.getUpdateCount(); + + int truncatedUpdateCount = 0; + + if (this.updateCount > Integer.MAX_VALUE) { + truncatedUpdateCount = Integer.MAX_VALUE; + } else { + truncatedUpdateCount = (int) this.updateCount; + } + + this.lastInsertId = rs.getUpdateID(); + + return truncatedUpdateCount; + } + } + + + /** + * @see StatementImpl#executeUpdate(String, int) + */ + public int executeUpdate(String sql, int returnGeneratedKeys) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) { + MySQLConnection locallyScopedConn = this.connection; + + // If this is a 'REPLACE' query, we need to be able to parse + // the 'info' message returned from the server to determine + // the actual number of keys generated. + boolean readInfoMsgState = locallyScopedConn + .isReadInfoMsgEnabled(); + locallyScopedConn.setReadInfoMsgEnabled(true); + + try { + return executeUpdate(sql, false, true); + } finally { + locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); + } + } + + return executeUpdate(sql); + } + } + + /** + * @see StatementImpl#executeUpdate(String, int[]) + */ + public int executeUpdate(String sql, int[] generatedKeyIndices) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) { + checkClosed(); + + MySQLConnection locallyScopedConn = this.connection; + + // If this is a 'REPLACE' query, we need to be able to parse + // the 'info' message returned from the server to determine + // the actual number of keys generated. + boolean readInfoMsgState = locallyScopedConn + .isReadInfoMsgEnabled(); + locallyScopedConn.setReadInfoMsgEnabled(true); + + try { + return executeUpdate(sql, false, true); + } finally { + locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); + } + } + + return executeUpdate(sql); + } + } + + /** + * @see StatementImpl#executeUpdate(String, String[]) + */ + public int executeUpdate(String sql, String[] generatedKeyNames) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) { + MySQLConnection locallyScopedConn = this.connection; + // If this is a 'REPLACE' query, we need to be able to parse + // the 'info' message returned from the server to determine + // the actual number of keys generated. + boolean readInfoMsgState = this.connection + .isReadInfoMsgEnabled(); + locallyScopedConn.setReadInfoMsgEnabled(true); + + try { + return executeUpdate(sql, false, true); + } finally { + locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); + } + } + + return executeUpdate(sql); + } + } + + /** + * Optimization to only use one calendar per-session, or calculate it for + * each call, depending on user configuration + */ + protected Calendar getCalendarInstanceForSessionOrNew() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.connection != null) { + return this.connection.getCalendarInstanceForSessionOrNew(); + } + // punt, no connection around + return new GregorianCalendar(); + } + } + + /** + * JDBC 2.0 Return the Connection that produced the Statement. + * + * @return the Connection that produced the Statement + * + * @throws SQLException + * if an error occurs + */ + public java.sql.Connection getConnection() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.connection; + } + } + + /** + * JDBC 2.0 Determine the fetch direction. + * + * @return the default fetch direction + * + * @exception SQLException + * if a database-access error occurs + */ + public int getFetchDirection() throws SQLException { + return java.sql.ResultSet.FETCH_FORWARD; + } + + /** + * JDBC 2.0 Determine the default fetch size. + * + * @return the number of rows to fetch at a time + * + * @throws SQLException + * if an error occurs + */ + public int getFetchSize() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.fetchSize; + } + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws SQLException + * DOCUMENT ME! + */ + public java.sql.ResultSet getGeneratedKeys() + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (!this.retrieveGeneratedKeys) { + throw SQLError.createSQLException(Messages.getString("Statement.GeneratedKeysNotRequested"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + + if (this.batchedGeneratedKeys == null) { + if (lastQueryIsOnDupKeyUpdate) { + return this.generatedKeysResults = getGeneratedKeysInternal(1); + } + return this.generatedKeysResults = getGeneratedKeysInternal(); + } + + Field[] fields = new Field[1]; + fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$ + fields[0].setConnection(this.connection); + + this.generatedKeysResults = com.mysql.jdbc.ResultSetImpl.getInstance(this.currentCatalog, fields, + new RowDataStatic(this.batchedGeneratedKeys), this.connection, + this, false); + + return this.generatedKeysResults; + } + } + + /* + * Needed because there's no concept of super.super to get to this + * implementation from ServerPreparedStatement when dealing with batched + * updates. + */ + protected ResultSetInternalMethods getGeneratedKeysInternal() + throws SQLException { + int numKeys = getUpdateCount(); + return getGeneratedKeysInternal(numKeys); + } + + protected ResultSetInternalMethods getGeneratedKeysInternal(int numKeys) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + Field[] fields = new Field[1]; + fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$ + fields[0].setConnection(this.connection); + fields[0].setUseOldNameMetadata(true); + + ArrayList rowSet = new ArrayList(); + + long beginAt = getLastInsertID(); + + if (beginAt < 0) { // looking at an UNSIGNED BIGINT that has overflowed + fields[0].setUnsigned(); + } + + if (this.results != null) { + String serverInfo = this.results.getServerInfo(); + + // + // Only parse server info messages for 'REPLACE' + // queries + // + if ((numKeys > 0) && (this.results.getFirstCharOfQuery() == 'R') + && (serverInfo != null) && (serverInfo.length() > 0)) { + numKeys = getRecordCountFromInfo(serverInfo); + } + + if ((beginAt != 0 /* BIGINT UNSIGNED can wrap the protocol representation */) && (numKeys > 0)) { + for (int i = 0; i < numKeys; i++) { + byte[][] row = new byte[1][]; + if (beginAt > 0) { + row[0] = StringUtils.getBytes(Long.toString(beginAt)); + } else { + byte[] asBytes = new byte[8]; + asBytes[7] = (byte) (beginAt & 0xff); + asBytes[6] = (byte) (beginAt >>> 8); + asBytes[5] = (byte) (beginAt >>> 16); + asBytes[4] = (byte) (beginAt >>> 24); + asBytes[3] = (byte) (beginAt >>> 32); + asBytes[2] = (byte) (beginAt >>> 40); + asBytes[1] = (byte) (beginAt >>> 48); + asBytes[0] = (byte) (beginAt >>> 56); + + BigInteger val = new BigInteger(1, asBytes); + + row[0] = val.toString().getBytes(); + } + rowSet.add(new ByteArrayRow(row, getExceptionInterceptor())); + beginAt += this.connection.getAutoIncrementIncrement(); + } + } + } + + com.mysql.jdbc.ResultSetImpl gkRs = com.mysql.jdbc.ResultSetImpl.getInstance(this.currentCatalog, fields, + new RowDataStatic(rowSet), this.connection, this, false); + + return gkRs; + } + } + + /** + * Returns the id used when profiling + * + * @return the id used when profiling. + */ + protected int getId() { + return this.statementId; + } + + /** + * getLastInsertID returns the value of the auto_incremented key after an + * executeQuery() or excute() call. + * + *

+ * This gets around the un-threadsafe behavior of "select LAST_INSERT_ID()" + * which is tied to the Connection that created this Statement, and + * therefore could have had many INSERTS performed before one gets a chance + * to call "select LAST_INSERT_ID()". + *

+ * + * @return the last update ID. + */ + public long getLastInsertID() { + try { + synchronized (checkClosed().getConnectionMutex()) { + return this.lastInsertId; + } + } catch (SQLException e) { + throw new RuntimeException(e); // evolve interface to throw SQLException + } + } + + /** + * getLongUpdateCount returns the current result as an update count, if the + * result is a ResultSet or there are no more results, -1 is returned. It + * should only be called once per result. + * + *

+ * This method returns longs as MySQL server versions newer than 3.22.4 + * return 64-bit values for update counts + *

+ * + * @return the current update count. + */ + public long getLongUpdateCount() { + try { + synchronized (checkClosed().getConnectionMutex()) { + if (this.results == null) { + return -1; + } + + if (this.results.reallyResult()) { + return -1; + } + + return this.updateCount; + } + } catch (SQLException e) { + throw new RuntimeException(e); // evolve interface to throw SQLException + } + } + + /** + * The maxFieldSize limit (in bytes) is the maximum amount of data returned + * for any column value; it only applies to BINARY, VARBINARY, + * LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR columns. If the limit is + * exceeded, the excess data is silently discarded. + * + * @return the current max column size limit; zero means unlimited + * + * @exception SQLException + * if a database access error occurs + */ + public int getMaxFieldSize() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.maxFieldSize; + } + } + + /** + * The maxRows limit is set to limit the number of rows that any ResultSet + * can contain. If the limit is exceeded, the excess rows are silently + * dropped. + * + * @return the current maximum row limit; zero means unlimited + * + * @exception SQLException + * if a database access error occurs + */ + public int getMaxRows() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.maxRows <= 0) { + return 0; + } + + return this.maxRows; + } + } + + /** + * getMoreResults moves to a Statement's next result. If it returns true, + * this result is a ResulSet. + * + * @return true if the next ResultSet is valid + * + * @exception SQLException + * if a database access error occurs + */ + public boolean getMoreResults() throws SQLException { + return getMoreResults(CLOSE_CURRENT_RESULT); + } + + /** + * @see StatementImpl#getMoreResults(int) + */ + public boolean getMoreResults(int current) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.results == null) { + return false; + } + + boolean streamingMode = createStreamingResultSet(); + + if (streamingMode) { + if (this.results.reallyResult()) { + while (this.results.next()); // need to drain remaining rows to get to server status + // which tells us whether more results actually exist or not + } + } + + ResultSetInternalMethods nextResultSet = this.results.getNextResultSet(); + + switch (current) { + case java.sql.Statement.CLOSE_CURRENT_RESULT: + + if (this.results != null) { + if (!(streamingMode || this.connection.getDontTrackOpenResources())) { + this.results.realClose(false); + } + + this.results.clearNextResult(); + } + + break; + + case java.sql.Statement.CLOSE_ALL_RESULTS: + + if (this.results != null) { + if (!(streamingMode || this.connection.getDontTrackOpenResources())) { + this.results.realClose(false); + } + + this.results.clearNextResult(); + } + + closeAllOpenResults(); + + break; + + case java.sql.Statement.KEEP_CURRENT_RESULT: + if (!this.connection.getDontTrackOpenResources()) { + this.openResults.add(this.results); + } + + this.results.clearNextResult(); // nobody besides us should + // ever need this value... + break; + + default: + throw SQLError.createSQLException(Messages + .getString("Statement.19"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + this.results = nextResultSet; + + if (this.results == null) { + this.updateCount = -1; + this.lastInsertId = -1; + } else if (this.results.reallyResult()) { + this.updateCount = -1; + this.lastInsertId = -1; + } else { + this.updateCount = this.results.getUpdateCount(); + this.lastInsertId = this.results.getUpdateID(); + } + + boolean moreResults = (this.results != null) && this.results.reallyResult(); + if (!moreResults) + checkAndPerformCloseOnCompletionAction(); + return moreResults; + } + } + + /** + * The queryTimeout limit is the number of seconds the driver will wait for + * a Statement to execute. If the limit is exceeded, a SQLException is + * thrown. + * + * @return the current query timeout limit in seconds; 0 = unlimited + * + * @exception SQLException + * if a database access error occurs + */ + public int getQueryTimeout() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.timeoutInMillis / 1000; + } + } + + /** + * Parses actual record count from 'info' message + * + * @param serverInfo + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private int getRecordCountFromInfo(String serverInfo) { + StringBuffer recordsBuf = new StringBuffer(); + int recordsCount = 0; + int duplicatesCount = 0; + + char c = (char) 0; + + int length = serverInfo.length(); + int i = 0; + + for (; i < length; i++) { + c = serverInfo.charAt(i); + + if (Character.isDigit(c)) { + break; + } + } + + recordsBuf.append(c); + i++; + + for (; i < length; i++) { + c = serverInfo.charAt(i); + + if (!Character.isDigit(c)) { + break; + } + + recordsBuf.append(c); + } + + recordsCount = Integer.parseInt(recordsBuf.toString()); + + StringBuffer duplicatesBuf = new StringBuffer(); + + for (; i < length; i++) { + c = serverInfo.charAt(i); + + if (Character.isDigit(c)) { + break; + } + } + + duplicatesBuf.append(c); + i++; + + for (; i < length; i++) { + c = serverInfo.charAt(i); + + if (!Character.isDigit(c)) { + break; + } + + duplicatesBuf.append(c); + } + + duplicatesCount = Integer.parseInt(duplicatesBuf.toString()); + + return recordsCount - duplicatesCount; + } + + /** + * getResultSet returns the current result as a ResultSet. It should only be + * called once per result. + * + * @return the current result set; null if there are no more + * + * @exception SQLException + * if a database access error occurs (why?) + */ + public java.sql.ResultSet getResultSet() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return ((this.results != null) && this.results.reallyResult()) ? (java.sql.ResultSet) this.results + : null; + } + } + + /** + * JDBC 2.0 Determine the result set concurrency. + * + * @return CONCUR_UPDATABLE or CONCUR_READONLY + * + * @throws SQLException + * if an error occurs + */ + public int getResultSetConcurrency() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.resultSetConcurrency; + } + } + + /** + * @see StatementImpl#getResultSetHoldability() + */ + public int getResultSetHoldability() throws SQLException { + return java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; + } + + protected ResultSetInternalMethods getResultSetInternal() { + try { + synchronized (checkClosed().getConnectionMutex()) { + return this.results; + } + } catch (SQLException e) { + return this.results; // you end up with the same thing as before, you'll get exception when actually trying to use it + } + } + + /** + * JDBC 2.0 Determine the result set type. + * + * @return the ResultSet type (SCROLL_SENSITIVE or SCROLL_INSENSITIVE) + * + * @throws SQLException + * if an error occurs. + */ + public int getResultSetType() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.resultSetType; + } + } + + /** + * getUpdateCount returns the current result as an update count, if the + * result is a ResultSet or there are no more results, -1 is returned. It + * should only be called once per result. + * + * @return the current result as an update count. + * + * @exception SQLException + * if a database access error occurs + */ + public int getUpdateCount() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.results == null) { + return -1; + } + + if (this.results.reallyResult()) { + return -1; + } + + int truncatedUpdateCount = 0; + + if (this.results.getUpdateCount() > Integer.MAX_VALUE) { + truncatedUpdateCount = Integer.MAX_VALUE; + } else { + truncatedUpdateCount = (int) this.results.getUpdateCount(); + } + + return truncatedUpdateCount; + } + } + + /** + * The first warning reported by calls on this Statement is returned. A + * Statement's execute methods clear its java.sql.SQLWarning chain. + * Subsequent Statement warnings will be chained to this + * java.sql.SQLWarning. + * + *

+ * The Warning chain is automatically cleared each time a statement is + * (re)executed. + *

+ * + *

+ * Note: If you are processing a ResultSet then any warnings + * associated with ResultSet reads will be chained on the ResultSet object. + *

+ * + * @return the first java.sql.SQLWarning or null + * + * @exception SQLException + * if a database access error occurs + */ + public java.sql.SQLWarning getWarnings() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + + if (this.clearWarningsCalled) { + return null; + } + + if (this.connection.versionMeetsMinimum(4, 1, 0)) { + SQLWarning pendingWarningsFromServer = SQLError + .convertShowWarningsToSQLWarnings(this.connection); + + if (this.warningChain != null) { + this.warningChain.setNextWarning(pendingWarningsFromServer); + } else { + this.warningChain = pendingWarningsFromServer; + } + + return this.warningChain; + } + + return this.warningChain; + } + } + + /** + * Closes this statement, and frees resources. + * + * @param calledExplicitly + * was this called from close()? + * + * @throws SQLException + * if an error occurs + */ + protected void realClose(boolean calledExplicitly, boolean closeOpenResults) + throws SQLException { + MySQLConnection locallyScopedConn = this.connection; + + if (locallyScopedConn == null) return; // already closed + + synchronized (locallyScopedConn.getConnectionMutex()) { + + // additional check in case Statement was closed + // while current thread was waiting for lock + if (this.isClosed) return; + + + if (this.useUsageAdvisor) { + if (!calledExplicitly) { + String message = Messages.getString("Statement.63") //$NON-NLS-1$ + + Messages.getString("Statement.64"); //$NON-NLS-1$ + + this.eventSink.consumeEvent(new ProfilerEvent( + ProfilerEvent.TYPE_WARN, + "", //$NON-NLS-1$ + this.currentCatalog, this.connectionId, this.getId(), + -1, System.currentTimeMillis(), 0, + Constants.MILLIS_I18N, null, this.pointOfOrigin, + message)); + } + } + + if (closeOpenResults) { + closeOpenResults = !(this.holdResultsOpenOverClose || + this.connection.getDontTrackOpenResources()); + } + + if (closeOpenResults) { + if (this.results != null) { + + try { + this.results.close(); + } catch (Exception ex) { + ; + } + } + + if (this.generatedKeysResults != null) { + + try { + this.generatedKeysResults.close(); + } catch (Exception ex) { + ; + } + } + + closeAllOpenResults(); + } + + if (this.connection != null) { + if (!this.connection.getDontTrackOpenResources()) { + this.connection.unregisterStatement(this); + } + } + + this.isClosed = true; + + this.results = null; + this.generatedKeysResults = null; + this.connection = null; + this.warningChain = null; + this.openResults = null; + this.batchedGeneratedKeys = null; + this.localInfileInputStream = null; + this.pingTarget = null; + } + } + + /** + * setCursorName defines the SQL cursor name that will be used by subsequent + * execute methods. This name can then be used in SQL positioned + * update/delete statements to identify the current row in the ResultSet + * generated by this statement. If a database doesn't support positioned + * update/delete, this method is a no-op. + * + *

+ * Note: This MySQL driver does not support cursors. + *

+ * + * @param name + * the new cursor name + * + * @exception SQLException + * if a database access error occurs + */ + public void setCursorName(String name) throws SQLException { + // No-op + } + + /** + * If escape scanning is on (the default), the driver will do escape + * substitution before sending the SQL to the database. + * + * @param enable + * true to enable; false to disable + * + * @exception SQLException + * if a database access error occurs + */ + public void setEscapeProcessing(boolean enable) + throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + this.doEscapeProcessing = enable; + } + } + + /** + * JDBC 2.0 Give a hint as to the direction in which the rows in a result + * set will be processed. The hint applies only to result sets created using + * this Statement object. The default value is ResultSet.FETCH_FORWARD. + * + * @param direction + * the initial direction for processing rows + * + * @exception SQLException + * if a database-access error occurs or direction is not one + * of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or + * ResultSet.FETCH_UNKNOWN + */ + public void setFetchDirection(int direction) throws SQLException { + switch (direction) { + case java.sql.ResultSet.FETCH_FORWARD: + case java.sql.ResultSet.FETCH_REVERSE: + case java.sql.ResultSet.FETCH_UNKNOWN: + break; + + default: + throw SQLError.createSQLException( + Messages.getString("Statement.5"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + } + + /** + * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should + * be fetched from the database when more rows are needed. The number of + * rows specified only affects result sets created using this statement. If + * the value specified is zero, then the hint is ignored. The default value + * is zero. + * + * @param rows + * the number of rows to fetch + * + * @exception SQLException + * if a database-access error occurs, or the condition 0 + * <= rows <= this.getMaxRows() is not satisfied. + */ + public void setFetchSize(int rows) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (((rows < 0) && (rows != Integer.MIN_VALUE)) + || ((this.maxRows > 0) && (rows > this + .getMaxRows()))) { + throw SQLError.createSQLException( + Messages.getString("Statement.7"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + this.fetchSize = rows; + } + } + + public void setHoldResultsOpenOverClose(boolean holdResultsOpenOverClose) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.holdResultsOpenOverClose = holdResultsOpenOverClose; + } + } catch (SQLException e) { + // FIXME: can't break interface at this point + } + } + + /** + * Sets the maxFieldSize + * + * @param max + * the new max column size limit; zero means unlimited + * + * @exception SQLException + * if size exceeds buffer size + */ + public void setMaxFieldSize(int max) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (max < 0) { + throw SQLError.createSQLException(Messages + .getString("Statement.11"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + int maxBuf = (this.connection != null) ? this.connection + .getMaxAllowedPacket() : MysqlIO.getMaxBuf(); + + if (max > maxBuf) { + throw SQLError.createSQLException(Messages.getString( + "Statement.13", //$NON-NLS-1$ + new Object[] { Long.valueOf(maxBuf) }), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + this.maxFieldSize = max; + } + } + + /** + * Set the maximum number of rows + * + * @param max + * the new max rows limit; zero means unlimited + * + * @exception SQLException + * if a database access error occurs + * + * @see getMaxRows + */ + public void setMaxRows(int max) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if ((max > MysqlDefs.MAX_ROWS) || (max < 0)) { + throw SQLError + .createSQLException( + Messages.getString("Statement.15") + max //$NON-NLS-1$ + + " > " //$NON-NLS-1$ //$NON-NLS-2$ + + MysqlDefs.MAX_ROWS + ".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (max == 0) { + max = -1; + } + + this.maxRows = max; + } + } + + /** + * Sets the queryTimeout limit + * + * @param seconds - + * the new query timeout limit in seconds + * + * @exception SQLException + * if a database access error occurs + */ + public void setQueryTimeout(int seconds) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (seconds < 0) { + throw SQLError.createSQLException(Messages + .getString("Statement.21"), //$NON-NLS-1$ + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ + } + + this.timeoutInMillis = seconds * 1000; + } + } + + /** + * Sets the concurrency for result sets generated by this statement + * + * @param concurrencyFlag + * DOCUMENT ME! + */ + void setResultSetConcurrency(int concurrencyFlag) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.resultSetConcurrency = concurrencyFlag; + } + } catch (SQLException e) { + // FIXME: Can't break interface atm, we'll get the exception later when + // you try and do something useful with a closed statement... + } + } + + /** + * Sets the result set type for result sets generated by this statement + * + * @param typeFlag + * DOCUMENT ME! + */ + void setResultSetType(int typeFlag) { + try { + synchronized (checkClosed().getConnectionMutex()) { + this.resultSetType = typeFlag; + } + } catch (SQLException e) { + // FIXME: Can't break interface atm, we'll get the exception later when + // you try and do something useful with a closed statement... + } + } + + protected void getBatchedGeneratedKeys(java.sql.Statement batchedStatement) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.retrieveGeneratedKeys) { + java.sql.ResultSet rs = null; + + try { + rs = batchedStatement.getGeneratedKeys(); + + while (rs.next()) { + this.batchedGeneratedKeys + .add(new ByteArrayRow(new byte[][] { rs.getBytes(1) }, getExceptionInterceptor())); + } + } finally { + if (rs != null) { + rs.close(); + } + } + } + } + } + + protected void getBatchedGeneratedKeys(int maxKeys) throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + if (this.retrieveGeneratedKeys) { + java.sql.ResultSet rs = null; + + try { + if (maxKeys == 0) + rs = getGeneratedKeysInternal(); + else + rs = getGeneratedKeysInternal(maxKeys); + + while (rs.next()) { + this.batchedGeneratedKeys + .add(new ByteArrayRow(new byte[][] { rs.getBytes(1) }, getExceptionInterceptor())); + } + } finally { + this.isImplicitlyClosingResults = true; + try { + if (rs != null) { + rs.close(); + } + } finally { + this.isImplicitlyClosingResults = false; + } + } + } + } + } + + /** + * @return + */ + private boolean useServerFetch() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return this.connection.isCursorFetchEnabled() && this.fetchSize > 0 + && this.resultSetConcurrency == ResultSet.CONCUR_READ_ONLY + && this.resultSetType == ResultSet.TYPE_FORWARD_ONLY; + } + } + + public boolean isClosed() throws SQLException { + MySQLConnection locallyScopedConn = this.connection; + if (locallyScopedConn == null) { + return true; + } + synchronized (locallyScopedConn.getConnectionMutex()) { + return this.isClosed; + } + } + + private boolean isPoolable = true; + + public boolean isPoolable() throws SQLException { + return this.isPoolable; + } + + public void setPoolable(boolean poolable) throws SQLException { + this.isPoolable = poolable; + } + + /** + * Returns true if this either implements the interface argument or is directly or indirectly a wrapper + * for an object that does. Returns false otherwise. If this implements the interface then return true, + * else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped + * object. If this does not implement the interface and is not a wrapper, return false. + * This method should be implemented as a low-cost operation compared to unwrap so that + * callers can use this method to avoid expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument should succeed. + * + * @param interfaces a Class defining an interface. + * @return true if this implements the interface or directly or indirectly wraps an object that does. + * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper + * for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + // This works for classes that aren't actually wrapping + // anything + return iface.isInstance(this); + } + + /** + * Returns an object that implements the given interface to allow access to non-standard methods, + * or standard methods not exposed by the proxy. + * The result may be either the object found to implement the interface or a proxy for that object. + * If the receiver implements the interface then that is the object. If the receiver is a wrapper + * and the wrapped object implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped object. If the receiver is not a + * wrapper and does not implement the interface, then an SQLException is thrown. + * + * @param iface A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the actual implementing object. + * @throws java.sql.SQLException If no object found that implements the interface + * @since 1.6 + */ + public Object unwrap(Class iface) throws java.sql.SQLException { + try { + // This works for classes that aren't actually wrapping + // anything + return Util.cast(iface, this); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); + } + } + + protected int findStartOfStatement(String sql) { + int statementStartPos = 0; + + if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) { + statementStartPos = sql.indexOf("*/"); + + if (statementStartPos == -1) { + statementStartPos = 0; + } else { + statementStartPos += 2; + } + } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "--") + || StringUtils.startsWithIgnoreCaseAndWs(sql, "#")) { + statementStartPos = sql.indexOf('\n'); + + if (statementStartPos == -1) { + statementStartPos = sql.indexOf('\r'); + + if (statementStartPos == -1) { + statementStartPos = 0; + } + } + } + + return statementStartPos; + } + + private InputStream localInfileInputStream; + + protected final boolean version5013OrNewer; + + public InputStream getLocalInfileInputStream() { + return this.localInfileInputStream; + } + + public void setLocalInfileInputStream(InputStream stream) { + this.localInfileInputStream = stream; + } + + public void setPingTarget(PingTarget pingTarget) { + this.pingTarget = pingTarget; + } + + public ExceptionInterceptor getExceptionInterceptor() { + return this.exceptionInterceptor; + } + + protected boolean containsOnDuplicateKeyInString(String sql) { + return getOnDuplicateKeyLocation(sql) != -1; + } + + protected int getOnDuplicateKeyLocation(String sql) { + return StringUtils.indexOfIgnoreCaseRespectMarker(0, + sql, "ON DUPLICATE KEY UPDATE ", "\"'`", "\"'`", !this.connection.isNoBackslashEscapesSet()); + } + + private boolean closeOnCompletion = false; + + public void closeOnCompletion() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + closeOnCompletion = true; + } + } + + public boolean isCloseOnCompletion() throws SQLException { + synchronized (checkClosed().getConnectionMutex()) { + return closeOnCompletion; + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,143 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +/** + * Implement this interface to be placed "in between" query execution, so that + * you can influence it. (currently experimental). + * + * StatementInterceptors are "chainable" when configured by the user, the + * results returned by the "current" interceptor will be passed on to the next + * on in the chain, from left-to-right order, as specified by the user in the + * JDBC configuration property "statementInterceptors". + * + * @version $Id$ + */ + +public interface StatementInterceptor extends Extension { + + /** + * Called once per connection that wants to use the interceptor + * + * The properties are the same ones passed in in the URL or arguments to + * Driver.connect() or DriverManager.getConnection(). + * + * @param conn the connection for which this interceptor is being created + * @param props configuration values as passed to the connection. Note that + * in order to support javax.sql.DataSources, configuration properties specific + * to an interceptor must be passed via setURL() on the + * DataSource. StatementInterceptor properties are not exposed via + * accessor/mutator methods on DataSources. + * + * @throws SQLException should be thrown if the the StatementInterceptor + * can not initialize itself. + */ + + public abstract void init(Connection conn, Properties props) throws SQLException; + + /** + * Called before the given statement is going to be sent to the + * server for processing. + * + * Interceptors are free to return a result set (which must implement the + * interface com.mysql.jdbc.ResultSetInternalMethods), and if so, + * the server will not execute the query, and the given result set will be + * returned to the application instead. + * + * This method will be called while the connection-level mutex is held, so + * it will only be called from one thread at a time. + * + * @param sql the SQL representation of the statement + * @param interceptedStatement the actual statement instance being intercepted + * @param connection the connection the statement is using (passed in to make + * thread-safe implementations straightforward) + * + * @return a result set that should be returned to the application instead + * of results that are created from actual execution of the intercepted + * statement. + * + * @throws SQLException if an error occurs during execution + * + * @see com.mysql.jdbc.ResultSetInternalMethods + */ + + public abstract ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException; + + /** + * Called after the given statement has been sent to the server + * for processing. + * + * Interceptors are free to inspect the "original" result set, and if a + * different result set is returned by the interceptor, it is used in place + * of the "original" result set. (the result set returned by the interceptor + * must implement the interface + * com.mysql.jdbc.ResultSetInternalMethods). + * + * This method will be called while the connection-level mutex is held, so + * it will only be called from one thread at a time. + * + * @param sql the SQL representation of the statement + * @param interceptedStatement the actual statement instance being intercepted + * @param connection the connection the statement is using (passed in to make + * thread-safe implementations straightforward) + * + * @return a result set that should be returned to the application instead + * of results that are created from actual execution of the intercepted + * statement. + * + * @throws SQLException if an error occurs during execution + * + * @see com.mysql.jdbc.ResultSetInternalMethods + */ + public abstract ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, + Connection connection) throws SQLException; + + /** + * Should the driver execute this interceptor only for the + * "original" top-level query, and not put it in the execution + * path for queries that may be executed from other interceptors? + * + * If an interceptor issues queries using the connection it was created for, + * and does not return true for this method, it must ensure + * that it does not cause infinite recursion. + * + * @return true if the driver should ensure that this interceptor is only + * executed for the top-level "original" query. + */ + public abstract boolean executeTopLevelOnly(); + + /** + * Called by the driver when this extension should release any resources + * it is holding and cleanup internally before the connection is + * closed. + */ + public abstract void destroy(); +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementInterceptorV2.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementInterceptorV2.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StatementInterceptorV2.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,133 @@ +/* + Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +public interface StatementInterceptorV2 extends Extension { + + /** + * Called once per connection that wants to use the interceptor + * + * The properties are the same ones passed in in the URL or arguments to + * Driver.connect() or DriverManager.getConnection(). + * + * @param conn the connection for which this interceptor is being created + * @param props configuration values as passed to the connection. Note that + * in order to support javax.sql.DataSources, configuration properties specific + * to an interceptor must be passed via setURL() on the + * DataSource. StatementInterceptor properties are not exposed via + * accessor/mutator methods on DataSources. + * + * @throws SQLException should be thrown if the the StatementInterceptor + * can not initialize itself. + */ + + public abstract void init(Connection conn, Properties props) throws SQLException; + + /** + * Called before the given statement is going to be sent to the + * server for processing. + * + * Interceptors are free to return a result set (which must implement the + * interface com.mysql.jdbc.ResultSetInternalMethods), and if so, + * the server will not execute the query, and the given result set will be + * returned to the application instead. + * + * This method will be called while the connection-level mutex is held, so + * it will only be called from one thread at a time. + * + * @param sql the SQL representation of the statement + * @param interceptedStatement the actual statement instance being intercepted + * @param connection the connection the statement is using (passed in to make + * thread-safe implementations straightforward) + * + * @return a result set that should be returned to the application instead + * of results that are created from actual execution of the intercepted + * statement. + * + * @throws SQLException if an error occurs during execution + * + * @see com.mysql.jdbc.ResultSetInternalMethods + */ + + public abstract ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException; + + /** + * Should the driver execute this interceptor only for the + * "original" top-level query, and not put it in the execution + * path for queries that may be executed from other interceptors? + * + * If an interceptor issues queries using the connection it was created for, + * and does not return true for this method, it must ensure + * that it does not cause infinite recursion. + * + * @return true if the driver should ensure that this interceptor is only + * executed for the top-level "original" query. + */ + public abstract boolean executeTopLevelOnly(); + + /** + * Called by the driver when this extension should release any resources + * it is holding and cleanup internally before the connection is + * closed. + */ + public abstract void destroy(); + + /** + * Called after the given statement has been sent to the server + * for processing, instead of the StatementAware postProcess() of the earlier + * api. + * + * Interceptors are free to inspect the "original" result set, and if a + * different result set is returned by the interceptor, it is used in place + * of the "original" result set. (the result set returned by the interceptor + * must implement the interface + * com.mysql.jdbc.ResultSetInternalMethods). + * + * This method will be called while the connection-level mutex is held, so + * it will only be called from one thread at a time. + * + * @param sql the SQL representation of the statement + * @param interceptedStatement the actual statement instance being intercepted + * @param connection the connection the statement is using (passed in to make + * thread-safe implementations straightforward) + * + * @return a result set that should be returned to the application instead + * of results that are created from actual execution of the intercepted + * statement. + * + * @throws SQLException if an error occurs during execution + * + * @see com.mysql.jdbc.ResultSetInternalMethods + */ + public abstract ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, + Connection connection, int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, + SQLException statementException) throws SQLException; +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StreamingNotifiable.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StreamingNotifiable.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StreamingNotifiable.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,30 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +public interface StreamingNotifiable { + + public abstract void setWasStreamingResults(); + +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/StringUtils.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/StringUtils.java (.../StringUtils.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/StringUtils.java (.../StringUtils.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.ByteArrayOutputStream; @@ -31,12 +30,16 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; - +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; import java.sql.SQLException; - import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; /** * Various utility methods for converting to/from byte arrays in the platform @@ -60,6 +63,34 @@ static final int WILD_COMPARE_NO_MATCH = -1; + private static final ConcurrentHashMap charsetsByAlias = + new ConcurrentHashMap(); + + private static final String platformEncoding = System.getProperty("file.encoding"); + + private static final String VALID_ID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789$_#@"; + + static Charset findCharset(String alias) throws UnsupportedEncodingException { + try { + Charset cs = charsetsByAlias.get(alias); + + if (cs == null) { + cs = Charset.forName(alias); + charsetsByAlias.putIfAbsent(alias, cs); + } + + return cs; + + // We re-throw these runtimes for compatibility with java.io + } catch (UnsupportedCharsetException uce) { + throw new UnsupportedEncodingException(alias); + } catch (IllegalCharsetNameException icne) { + throw new UnsupportedEncodingException(alias); + } catch (IllegalArgumentException iae) { + throw new UnsupportedEncodingException(alias); + } + } + static { for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { allBytes[i - Byte.MIN_VALUE] = (byte) i; @@ -99,7 +130,7 @@ if (toPlainStringMethod != null) { try { - return (String) toPlainStringMethod.invoke(decimal, null); + return (String) toPlainStringMethod.invoke(decimal, (Object[])null); } catch (InvocationTargetException invokeEx) { // that's okay, we fall-through to decimal.toString() } catch (IllegalAccessException accessEx) { @@ -120,8 +151,8 @@ * * @return ... */ - public static final String dumpAsHex(byte[] byteBuffer, int length) { - StringBuffer outputBuf = new StringBuffer(length * 4); + public static String dumpAsHex(byte[] byteBuffer, int length) { + StringBuilder outputBuilder = new StringBuilder(length * 4); int p = 0; int rows = length / 8; @@ -133,26 +164,28 @@ String hexVal = Integer.toHexString(byteBuffer[ptemp] & 0xff); if (hexVal.length() == 1) { - hexVal = "0" + hexVal; //$NON-NLS-1$ + hexVal = "0" + hexVal; } - outputBuf.append(hexVal + " "); //$NON-NLS-1$ + outputBuilder.append(hexVal + " "); ptemp++; } - outputBuf.append(" "); //$NON-NLS-1$ + outputBuilder.append(" "); for (int j = 0; j < 8; j++) { - if ((byteBuffer[p] > 32) && (byteBuffer[p] < 127)) { - outputBuf.append((char) byteBuffer[p] + " "); //$NON-NLS-1$ + int b = 0xff & byteBuffer[p]; + + if (b > 32 && b < 127) { + outputBuilder.append((char) b + " "); } else { - outputBuf.append(". "); //$NON-NLS-1$ + outputBuilder.append(". "); } p++; } - outputBuf.append("\n"); //$NON-NLS-1$ + outputBuilder.append("\n"); } int n = 0; @@ -161,30 +194,32 @@ String hexVal = Integer.toHexString(byteBuffer[i] & 0xff); if (hexVal.length() == 1) { - hexVal = "0" + hexVal; //$NON-NLS-1$ + hexVal = "0" + hexVal; } - outputBuf.append(hexVal + " "); //$NON-NLS-1$ + outputBuilder.append(hexVal + " "); n++; } for (int i = n; i < 8; i++) { - outputBuf.append(" "); //$NON-NLS-1$ + outputBuilder.append(" "); } - outputBuf.append(" "); //$NON-NLS-1$ + outputBuilder.append(" "); for (int i = p; i < length; i++) { - if ((byteBuffer[i] > 32) && (byteBuffer[i] < 127)) { - outputBuf.append((char) byteBuffer[i] + " "); //$NON-NLS-1$ + int b = 0xff & byteBuffer[i]; + + if (b > 32 && b < 127) { + outputBuilder.append((char) b + " "); } else { - outputBuf.append(". "); //$NON-NLS-1$ + outputBuilder.append(". "); } } - outputBuf.append("\n"); //$NON-NLS-1$ + outputBuilder.append("\n"); - return outputBuf.toString(); + return outputBuilder.toString(); } private static boolean endsWith(byte[] dataFrom, String suffix) { @@ -206,18 +241,16 @@ * the original bytes in SJIS format * @param origString * the string that had .getBytes() called on it - * @param offset - * where to start converting from - * @param length - * how many characters to convert. * * @return byte[] with 0x5c escaped */ - public static byte[] escapeEasternUnicodeByteStream(byte[] origBytes, - String origString, int offset, int length) { - if ((origBytes == null) || (origBytes.length == 0)) { - return origBytes; + public static byte[] escapeEasternUnicodeByteStream(byte[] origBytes, String origString) { + if (origBytes == null) { + return null; } + if (origBytes.length == 0) { + return new byte[0]; + } int bytesLen = origBytes.length; int bufIndex = 0; @@ -337,6 +370,24 @@ return 0; } + public static char firstAlphaCharUc(String searchIn, int startAt) { + if (searchIn == null) { + return 0; + } + + int length = searchIn.length(); + + for (int i = startAt; i < length; i++) { + char c = searchIn.charAt(i); + + if (Character.isLetter(c)) { + return Character.toUpperCase(c); + } + } + + return 0; + } + /** * Adds '+' to decimal numbers that are positive (MySQL doesn't understand * them otherwise @@ -346,298 +397,289 @@ * * @return String the string with a '+' added (if needed) */ - public static final String fixDecimalExponent(String dString) { - int ePos = dString.indexOf("E"); //$NON-NLS-1$ + public static String fixDecimalExponent(String dString) { + int ePos = dString.indexOf('E'); if (ePos == -1) { - ePos = dString.indexOf("e"); //$NON-NLS-1$ + ePos = dString.indexOf('e'); } if (ePos != -1) { if (dString.length() > (ePos + 1)) { char maybeMinusChar = dString.charAt(ePos + 1); if (maybeMinusChar != '-' && maybeMinusChar != '+') { - StringBuffer buf = new StringBuffer(dString.length() + 1); - buf.append(dString.substring(0, ePos + 1)); - buf.append('+'); - buf.append(dString.substring(ePos + 1, dString.length())); - dString = buf.toString(); + StringBuilder strBuilder = new StringBuilder(dString.length() + 1); + strBuilder.append(dString.substring(0, ePos + 1)); + strBuilder.append('+'); + strBuilder.append(dString.substring(ePos + 1, dString.length())); + dString = strBuilder.toString(); } } } return dString; } - public static final byte[] getBytes(char[] c, - SingleByteCharsetConverter converter, String encoding, - String serverEncoding, boolean parserKnowsUnicode) + /** + * Returns the byte[] representation of the given char[] (re)using the given charset converter, and the given + * encoding. + */ + public static byte[] getBytes(char[] c, SingleByteCharsetConverter converter, String encoding, + String serverEncoding, boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor) throws SQLException { try { - byte[] b = null; + byte[] b; if (converter != null) { b = converter.toBytes(c); } else if (encoding == null) { - b = new String(c).getBytes(); + b = getBytes(c); } else { - String s = new String(c); + b = getBytes(c, encoding); - b = s.getBytes(encoding); + if (!parserKnowsUnicode + && (encoding.equalsIgnoreCase("SJIS") || encoding.equalsIgnoreCase("BIG5") || encoding + .equalsIgnoreCase("GBK"))) { - if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$ - if (!encoding.equalsIgnoreCase(serverEncoding)) { - b = escapeEasternUnicodeByteStream(b, s, 0, s.length()); + b = escapeEasternUnicodeByteStream(b, new String(c)); } } } return b; } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException(Messages.getString("StringUtils.5") //$NON-NLS-1$ - + encoding + Messages.getString("StringUtils.6"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + throw SQLError.createSQLException( + Messages.getString("StringUtils.0") + encoding + Messages.getString("StringUtils.1"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } } - public static final byte[] getBytes(char[] c, - SingleByteCharsetConverter converter, String encoding, - String serverEncoding, int offset, int length, - boolean parserKnowsUnicode) throws SQLException { + /** + * Returns the byte[] representation of subset of the given char[] (re)using the given charset converter, and the + * given encoding. + */ + public static byte[] getBytes(char[] c, SingleByteCharsetConverter converter, String encoding, + String serverEncoding, int offset, int length, boolean parserKnowsUnicode, + ExceptionInterceptor exceptionInterceptor) throws SQLException { try { - byte[] b = null; + byte[] b; if (converter != null) { b = converter.toBytes(c, offset, length); } else if (encoding == null) { - byte[] temp = new String(c, offset, length).getBytes(); - - length = temp.length; - - b = new byte[length]; - System.arraycopy(temp, 0, b, 0, length); + b = getBytes(c, offset, length); } else { - String s = new String(c, offset, length); + b = getBytes(c, offset, length, encoding); - byte[] temp = s.getBytes(encoding); + if (!parserKnowsUnicode + && (encoding.equalsIgnoreCase("SJIS") || encoding.equalsIgnoreCase("BIG5") || encoding + .equalsIgnoreCase("GBK"))) { - length = temp.length; - - b = new byte[length]; - System.arraycopy(temp, 0, b, 0, length); - - if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$ - if (!encoding.equalsIgnoreCase(serverEncoding)) { - b = escapeEasternUnicodeByteStream(b, s, offset, length); + b = escapeEasternUnicodeByteStream(b, new String(c, offset, length)); } } } return b; } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException(Messages.getString("StringUtils.10") //$NON-NLS-1$ - + encoding + Messages.getString("StringUtils.11"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + throw SQLError.createSQLException( + Messages.getString("StringUtils.0") + encoding + Messages.getString("StringUtils.1"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } } - public static final byte[] getBytes(char[] c, String encoding, - String serverEncoding, boolean parserKnowsUnicode, Connection conn) - throws SQLException { + /** + * Returns the byte[] representation of the given char[] (re)using a cached charset converter, and the given + * encoding. + */ + public static byte[] getBytes(char[] c, String encoding, String serverEncoding, boolean parserKnowsUnicode, + MySQLConnection conn, ExceptionInterceptor exceptionInterceptor) throws SQLException { try { - - SingleByteCharsetConverter converter = null; - - if (conn != null) { - converter = conn.getCharsetConverter(encoding); - } else { - converter = SingleByteCharsetConverter.getInstance(encoding, null); - } + SingleByteCharsetConverter converter = conn != null ? conn.getCharsetConverter(encoding) + : SingleByteCharsetConverter.getInstance(encoding, null); - return getBytes(c, converter, encoding, serverEncoding, - parserKnowsUnicode); + return getBytes(c, converter, encoding, serverEncoding, parserKnowsUnicode, exceptionInterceptor); } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException(Messages.getString("StringUtils.0") //$NON-NLS-1$ - + encoding + Messages.getString("StringUtils.1"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + throw SQLError.createSQLException( + Messages.getString("StringUtils.0") + encoding + Messages.getString("StringUtils.1"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } } /** - * Returns the byte[] representation of the given string (re)using the given - * charset converter, and the given encoding. - * - * @param s - * the string to convert - * @param converter - * the converter to reuse - * @param encoding - * the character encoding to use - * @param serverEncoding - * DOCUMENT ME! - * @param parserKnowsUnicode - * DOCUMENT ME! - * - * @return byte[] representation of the string - * - * @throws SQLException - * if an encoding unsupported by the JVM is supplied. + * Returns the byte[] representation of the given string (re)using the given charset converter, and the given + * encoding. */ - public static final byte[] getBytes(String s, - SingleByteCharsetConverter converter, String encoding, - String serverEncoding, boolean parserKnowsUnicode) + public static byte[] getBytes(String s, SingleByteCharsetConverter converter, String encoding, + String serverEncoding, boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor) throws SQLException { try { - byte[] b = null; + byte[] b; if (converter != null) { b = converter.toBytes(s); } else if (encoding == null) { - b = s.getBytes(); + b = getBytes(s); } else { - b = s.getBytes(encoding); + b = getBytes(s, encoding); - if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$ + if (!parserKnowsUnicode + && (encoding.equalsIgnoreCase("SJIS") || encoding.equalsIgnoreCase("BIG5") || encoding + .equalsIgnoreCase("GBK"))) { if (!encoding.equalsIgnoreCase(serverEncoding)) { - b = escapeEasternUnicodeByteStream(b, s, 0, s.length()); + b = escapeEasternUnicodeByteStream(b, s); } } } return b; } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException(Messages.getString("StringUtils.5") //$NON-NLS-1$ - + encoding + Messages.getString("StringUtils.6"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + throw SQLError.createSQLException( + Messages.getString("StringUtils.5") + encoding + Messages.getString("StringUtils.6"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } } /** - * DOCUMENT ME! - * - * @param s - * DOCUMENT ME! - * @param converter - * DOCUMENT ME! - * @param encoding - * DOCUMENT ME! - * @param serverEncoding - * DOCUMENT ME! - * @param offset - * DOCUMENT ME! - * @param length - * DOCUMENT ME! - * @param parserKnowsUnicode - * DOCUMENT ME! - * - * @return DOCUMENT ME! - * - * @throws SQLException - * DOCUMENT ME! + * Returns the byte[] representation of a substring of the given string (re)using the given charset converter, and + * the given encoding. */ - public static final byte[] getBytes(String s, - SingleByteCharsetConverter converter, String encoding, - String serverEncoding, int offset, int length, - boolean parserKnowsUnicode) throws SQLException { + public static byte[] getBytes(String s, SingleByteCharsetConverter converter, String encoding, + String serverEncoding, int offset, int length, boolean parserKnowsUnicode, + ExceptionInterceptor exceptionInterceptor) throws SQLException { try { - byte[] b = null; + byte[] b; if (converter != null) { b = converter.toBytes(s, offset, length); } else if (encoding == null) { - byte[] temp = s.substring(offset, offset + length).getBytes(); - - length = temp.length; - - b = new byte[length]; - System.arraycopy(temp, 0, b, 0, length); + b = getBytes(s, offset, length); } else { + s = s.substring(offset, offset + length); + b = getBytes(s, encoding); - byte[] temp = s.substring(offset, offset + length) - .getBytes(encoding); + if (!parserKnowsUnicode + && (encoding.equalsIgnoreCase("SJIS") || encoding.equalsIgnoreCase("BIG5") || encoding + .equalsIgnoreCase("GBK"))) { - length = temp.length; - - b = new byte[length]; - System.arraycopy(temp, 0, b, 0, length); - - if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$ - || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$ - if (!encoding.equalsIgnoreCase(serverEncoding)) { - b = escapeEasternUnicodeByteStream(b, s, offset, length); + b = escapeEasternUnicodeByteStream(b, s); } } } return b; } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException(Messages.getString("StringUtils.10") //$NON-NLS-1$ - + encoding + Messages.getString("StringUtils.11"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + throw SQLError.createSQLException( + Messages.getString("StringUtils.5") + encoding + Messages.getString("StringUtils.6"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } } /** - * Returns the byte[] representation of the given string using given + * Returns the byte[] representation of the given string (re)using a cached charset converter, and the given * encoding. - * - * @param s - * the string to convert - * @param encoding - * the character encoding to use - * @param parserKnowsUnicode - * DOCUMENT ME! - * - * @return byte[] representation of the string - * - * @throws SQLException - * if an encoding unsupported by the JVM is supplied. */ - public static final byte[] getBytes(String s, String encoding, - String serverEncoding, boolean parserKnowsUnicode, Connection conn) + public static byte[] getBytes(String s, String encoding, String serverEncoding, boolean parserKnowsUnicode, + MySQLConnection conn, ExceptionInterceptor exceptionInterceptor) throws SQLException { + try { + SingleByteCharsetConverter converter = conn != null ? conn.getCharsetConverter(encoding) + : SingleByteCharsetConverter.getInstance(encoding, null); + + return getBytes(s, converter, encoding, serverEncoding, parserKnowsUnicode, exceptionInterceptor); + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException( + Messages.getString("StringUtils.5") + encoding + Messages.getString("StringUtils.6"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } + + /** + * Returns the byte[] representation of a substring of the given string (re)using a cached charset converter, and + * the given encoding. + */ + public static final byte[] getBytes(String s, String encoding, String serverEncoding, int offset, int length, + boolean parserKnowsUnicode, MySQLConnection conn, ExceptionInterceptor exceptionInterceptor) throws SQLException { try { - SingleByteCharsetConverter converter = null; - - if (conn != null) { - converter = conn.getCharsetConverter(encoding); + SingleByteCharsetConverter converter = conn != null ? conn.getCharsetConverter(encoding) + : SingleByteCharsetConverter.getInstance(encoding, null); + + return getBytes(s, converter, encoding, serverEncoding, offset, length, parserKnowsUnicode, + exceptionInterceptor); + } catch (UnsupportedEncodingException uee) { + throw SQLError.createSQLException( + Messages.getString("StringUtils.5") + encoding + Messages.getString("StringUtils.6"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + } + + /** + * Returns the byte[] representation of the given string properly wrapped between the given char delimiters, + * (re)using the given charset converter, and the given encoding. + */ + public static byte[] getBytesWrapped(String s, char beginWrap, char endWrap, SingleByteCharsetConverter converter, + String encoding, String serverEncoding, boolean parserKnowsUnicode, + ExceptionInterceptor exceptionInterceptor) throws SQLException { + try { + byte[] b; + + if (converter != null) { + b = converter.toBytesWrapped(s, beginWrap, endWrap); + } else if (encoding == null) { + StringBuilder strBuilder = new StringBuilder(s.length() + 2); + strBuilder.append(beginWrap); + strBuilder.append(s); + strBuilder.append(endWrap); + + b = getBytes(strBuilder.toString()); } else { - converter = SingleByteCharsetConverter.getInstance(encoding, null); + StringBuilder strBuilder = new StringBuilder(s.length() + 2); + strBuilder.append(beginWrap); + strBuilder.append(s); + strBuilder.append(endWrap); + + s = strBuilder.toString(); + b = getBytes(s, encoding); + + if (!parserKnowsUnicode + && (encoding.equalsIgnoreCase("SJIS") || encoding.equalsIgnoreCase("BIG5") || encoding + .equalsIgnoreCase("GBK"))) { + + if (!encoding.equalsIgnoreCase(serverEncoding)) { + b = escapeEasternUnicodeByteStream(b, s); + } + } } - return getBytes(s, converter, encoding, serverEncoding, - parserKnowsUnicode); + return b; } catch (UnsupportedEncodingException uee) { - throw SQLError.createSQLException(Messages.getString("StringUtils.0") //$NON-NLS-1$ - + encoding + Messages.getString("StringUtils.1"), - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ + throw SQLError.createSQLException( + Messages.getString("StringUtils.10") + encoding + Messages.getString("StringUtils.11"), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } } + public static int getInt(byte[] buf) throws NumberFormatException { + return getInt(buf, 0, buf.length); + } + public static int getInt(byte[] buf, int offset, int endPos) throws NumberFormatException { int base = 10; int s = offset; /* Skip white space. */ - while (Character.isWhitespace((char) buf[s]) && (s < endPos)) { + while (s < endPos && Character.isWhitespace((char) buf[s])) { ++s; } if (s == endPos) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } /* Check for a sign. */ @@ -689,33 +731,33 @@ } if (s == save) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } if (overflow) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } /* Return the result of the appropriate sign. */ return (negative ? (-i) : i); } - public static int getInt(byte[] buf) throws NumberFormatException { - return getInt(buf, 0, buf.length); - } - public static long getLong(byte[] buf) throws NumberFormatException { + return getLong(buf, 0, buf.length); + } + + public static long getLong(byte[] buf, int offset, int endpos) throws NumberFormatException { int base = 10; - int s = 0; + int s = offset; /* Skip white space. */ - while (Character.isWhitespace((char) buf[s]) && (s < buf.length)) { + while (s < endpos && Character.isWhitespace((char) buf[s])) { ++s; } - if (s == buf.length) { - throw new NumberFormatException(new String(buf)); + if (s == endpos) { + throw new NumberFormatException(StringUtils.toString(buf)); } /* Check for a sign. */ @@ -741,7 +783,7 @@ boolean overflow = false; long i = 0; - for (; s < buf.length; s++) { + for (; s < endpos; s++) { char c = (char) buf[s]; if (Character.isDigit(c)) { @@ -766,29 +808,33 @@ } if (s == save) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } if (overflow) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } /* Return the result of the appropriate sign. */ return (negative ? (-i) : i); } public static short getShort(byte[] buf) throws NumberFormatException { + return getShort(buf, 0, buf.length); + } + + public static short getShort(byte[] buf, int offset, int endpos) throws NumberFormatException { short base = 10; - int s = 0; + int s = offset; /* Skip white space. */ - while (Character.isWhitespace((char) buf[s]) && (s < buf.length)) { + while (s < endpos && Character.isWhitespace((char) buf[s])) { ++s; } - if (s == buf.length) { - throw new NumberFormatException(new String(buf)); + if (s == endpos) { + throw new NumberFormatException(StringUtils.toString(buf)); } /* Check for a sign. */ @@ -814,7 +860,7 @@ boolean overflow = false; short i = 0; - for (; s < buf.length; s++) { + for (; s < endpos; s++) { char c = (char) buf[s]; if (Character.isDigit(c)) { @@ -839,11 +885,11 @@ } if (s == save) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } if (overflow) { - throw new NumberFormatException(new String(buf)); + throw new NumberFormatException(StringUtils.toString(buf)); } /* Return the result of the appropriate sign. */ @@ -861,8 +907,6 @@ int stringLength = searchIn.length(); int stopSearchingAt = stringLength - patternLength; - int i = startingPosition; - if (patternLength == 0) { return -1; } @@ -872,49 +916,38 @@ char firstCharOfPatternUc = Character.toUpperCase(searchFor.charAt(0)); char firstCharOfPatternLc = Character.toLowerCase(searchFor.charAt(0)); - lookForFirstChar: while (true) { - while ((i < stopSearchingAt) - && (Character.toUpperCase(searchIn.charAt(i)) != firstCharOfPatternUc) - && Character.toLowerCase(searchIn.charAt(i)) != firstCharOfPatternLc) { - i++; - } + // note, this also catches the case where patternLength > stringLength + for (int i = startingPosition; i <= stopSearchingAt; i++) { + if (isNotEqualIgnoreCharCase(searchIn, firstCharOfPatternUc, + firstCharOfPatternLc, i)) { + // find the first occurrence of the first character of searchFor in searchIn + while (++i <= stopSearchingAt && (isNotEqualIgnoreCharCase(searchIn, firstCharOfPatternUc, + firstCharOfPatternLc, i))); + } - if (i > stopSearchingAt) { - return -1; - } + if (i <= stopSearchingAt /* searchFor might be one character long! */) { + // walk searchIn and searchFor in lock-step starting just past the first match,bail out if not + // a match, or we've hit the end of searchFor... + int j = i + 1; + int end = j + patternLength - 1; + for (int k = 1; j < end && (Character.toLowerCase(searchIn.charAt(j)) == + Character.toLowerCase(searchFor.charAt(k)) || Character.toUpperCase(searchIn.charAt(j)) == + Character.toUpperCase(searchFor.charAt(k))); j++, k++); - int j = i + 1; - int end = (j + patternLength) - 1; + if (j == end) { + return i; + } + } + } + + return -1; + } - int k = 1; // start at second char of pattern - - while (j < end) { - int searchInPos = j++; - int searchForPos = k++; - - if (Character.toUpperCase(searchIn.charAt(searchInPos)) != Character - .toUpperCase(searchFor.charAt(searchForPos))) { - i++; - - // start over - continue lookForFirstChar; - } - - // Georgian and Turkish locales don't have same convention, so - // need to check lowercase - // too! - if (Character.toLowerCase(searchIn.charAt(searchInPos)) != Character - .toLowerCase(searchFor.charAt(searchForPos))) { - i++; - - // start over - continue lookForFirstChar; - } - } - - return i; // found entire pattern - } + private final static boolean isNotEqualIgnoreCharCase(String searchIn, + char firstCharOfPatternUc, char firstCharOfPatternLc, int i) { + return Character.toLowerCase(searchIn.charAt(i)) != firstCharOfPatternLc && Character.toUpperCase(searchIn.charAt(i)) != firstCharOfPatternUc; } + /** * DOCUMENT ME! @@ -935,7 +968,7 @@ boolean allowBackslashEscapes) { char contextMarker = Character.MIN_VALUE; boolean escaped = false; - int markerTypeFound = -1; + int markerTypeFound = 0; int srcLength = src.length(); int ind = 0; @@ -944,16 +977,16 @@ if (allowBackslashEscapes && c == '\\') { escaped = !escaped; - } else if (markerTypeFound != -1 && c == markerCloses.charAt(markerTypeFound) && !escaped) { + } else if (contextMarker != Character.MIN_VALUE && c == markerCloses.charAt(markerTypeFound) && !escaped) { contextMarker = Character.MIN_VALUE; - markerTypeFound = -1; } else if ((ind = marker.indexOf(c)) != -1 && !escaped && contextMarker == Character.MIN_VALUE) { markerTypeFound = ind; contextMarker = c; - } else if (c == target.charAt(0) && !escaped + } else if ((Character.toUpperCase(c) == Character.toUpperCase(target.charAt(0)) || + Character.toLowerCase(c) == Character.toLowerCase(target.charAt(0))) && !escaped && contextMarker == Character.MIN_VALUE) { - if (indexOfIgnoreCase(i, src, target) != -1) + if (startsWithIgnoreCase(src, i, target)) return i; } } @@ -1008,10 +1041,10 @@ * @throws IllegalArgumentException * DOCUMENT ME! */ - public static final List split(String stringToSplit, String delimitter, + public static final List split(String stringToSplit, String delimitter, boolean trim) { if (stringToSplit == null) { - return new ArrayList(); + return new ArrayList(); } if (delimitter == null) { @@ -1021,7 +1054,7 @@ StringTokenizer tokenizer = new StringTokenizer(stringToSplit, delimitter, false); - List splitTokens = new ArrayList(tokenizer.countTokens()); + List splitTokens = new ArrayList(tokenizer.countTokens()); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); @@ -1051,10 +1084,10 @@ * @throws IllegalArgumentException * DOCUMENT ME! */ - public static final List split(String stringToSplit, String delimiter, + public static final List split(String stringToSplit, String delimiter, String markers, String markerCloses, boolean trim) { if (stringToSplit == null) { - return new ArrayList(); + return new ArrayList(); } if (delimiter == null) { @@ -1064,7 +1097,7 @@ int delimPos = 0; int currentPos = 0; - List splitTokens = new ArrayList(); + List splitTokens = new ArrayList(); while ((delimPos = indexOfIgnoreCaseRespectMarker(currentPos, stringToSplit, delimiter, markers, markerCloses, false)) != -1) { @@ -1136,7 +1169,7 @@ } /** - * Determines whether or not the sting 'searchIn' contains the string + * Determines whether or not the string 'searchIn' contains the string * 'searchFor', disregarding case,leading whitespace and non-alphanumeric * characters. * @@ -1169,7 +1202,7 @@ } /** - * Determines whether or not the sting 'searchIn' contains the string + * Determines whether or not the string 'searchIn' contains the string * 'searchFor', disregarding case and leading whitespace * * @param searchIn @@ -1185,7 +1218,7 @@ } /** - * Determines whether or not the sting 'searchIn' contains the string + * Determines whether or not the string 'searchIn' contains the string * 'searchFor', disregarding case and leading whitespace * * @param searchIn @@ -1216,6 +1249,26 @@ } /** + * Determines whether or not the string 'searchIn' starts with one of the strings in 'searchFor', disregarding case + * and leading whitespace + * + * @param searchIn + * the string to search in + * @param searchFor + * the string array to search for + * + * @return the 'searchFor' array index that matched or -1 if none matches + */ + public static int startsWithIgnoreCaseAndWs(String searchIn, String[] searchFor) { + for (int i = 0; i < searchFor.length; i++) { + if (startsWithIgnoreCaseAndWs(searchIn, searchFor[i], 0)) { + return i; + } + } + return -1; + } + + /** * @param bytesToStrip * @param prefix * @param suffix @@ -1431,7 +1484,7 @@ : WILD_COMPARE_MATCH_NO_WILD); } - static byte[] s2b(String s, Connection conn) throws SQLException { + static byte[] s2b(String s, MySQLConnection conn) throws SQLException { if (s == null) { return null; } @@ -1459,7 +1512,7 @@ return s.getBytes(); } - + public static int lastIndexOf(byte[] s, char c) { if (s == null) { return -1; @@ -1490,6 +1543,10 @@ return -1; } + public static boolean isNullOrEmpty(String toTest) { + return (toTest == null || toTest.length() == 0); + } + /** * Returns the given string, with comments removed * @@ -1518,7 +1575,7 @@ return null; } - StringBuffer buf = new StringBuffer(src.length()); + StringBuilder strBuilder = new StringBuilder(src.length()); // It's just more natural to deal with this as a stream // when parsing..This code is currently only called when @@ -1592,10 +1649,10 @@ currentChar = sourceReader.read(); if (currentChar == -1 || currentChar != '-') { - buf.append('-'); + strBuilder.append('-'); if (currentChar != -1) { - buf.append(currentChar); + strBuilder.append(currentChar); } continue; @@ -1609,13 +1666,468 @@ } if (currentChar != -1) { - buf.append((char) currentChar); + strBuilder.append((char) currentChar); } } } catch (IOException ioEx) { // we'll never see this from a StringReader } - return buf.toString(); + return strBuilder.toString(); } + + /** + * Next two functions are to help DBMD check if + * the given string is in form of database.name and return it + * as "database";"name" with comments removed. + * If string is NULL or wildcard (%), returns null and exits. + * + * First, we sanitize... + * + * @param src + * the source string + * @return the input string with all comment-delimited data removed + */ + public static String sanitizeProcOrFuncName(String src) { + if ((src == null) || (src.equals("%"))) { + return null; + } + + return src; + } + + /** + * Next we check if there is anything to split. If so + * we return result in form of "database";"name" + * If string is NULL or wildcard (%), returns null and exits. + * + * @param src + * the source string + * @param cat + * Catalog, if available + * @param quotId + * quoteId as defined on server + * @param isNoBslashEscSet + * Is our connection in BackSlashEscape mode + * @return the input string with all comment-delimited data removed + */ + public static List splitDBdotName(String src, String cat, String quotId, + boolean isNoBslashEscSet) { + if ((src == null) || (src.equals("%"))) { + return new ArrayList(); + } + + boolean isQuoted = StringUtils.indexOfIgnoreCase(0,src, quotId) > -1; + + + String retval = src; + String tmpCat = cat; + //I.e., what if database is named `MyDatabase 1.0.0`... thus trueDotIndex + int trueDotIndex = -1; + if (!" ".equals(quotId)) { + //Presumably, if there is a database name attached and it contains dots, then it should + //be quoted so we first check for that + if (isQuoted) { + trueDotIndex = StringUtils.indexOfIgnoreCase(0, + retval, quotId + "." + quotId); + } else { + //NOT quoted, fetch first DOT + // ex: cStmt = this.conn.prepareCall("{call bug57022.procbug57022(?, ?)}"); + trueDotIndex = StringUtils.indexOfIgnoreCase(0, + retval, "."); + } + } else { + trueDotIndex = retval.indexOf("."); + } + + List retTokens = new ArrayList(2); + + if (trueDotIndex != -1) { + //There is a catalog attached + if (isQuoted) { + tmpCat = StringUtils.toString(StringUtils.stripEnclosure(retval.substring(0, trueDotIndex+1) + .getBytes(), quotId, quotId)); + if (StringUtils.startsWithIgnoreCaseAndWs(tmpCat, quotId)) { + tmpCat = tmpCat.substring(1, tmpCat.length() - 1); + } + + retval = retval.substring(trueDotIndex + 2); + retval = StringUtils.toString(StringUtils.stripEnclosure(retval + .getBytes(), quotId, quotId)); + } else { + //NOT quoted, adjust indexOf + tmpCat = retval.substring(0, trueDotIndex); + retval = retval.substring(trueDotIndex + 1); + } + } else { + //No catalog attached, strip retval and return + retval = StringUtils.toString(StringUtils.stripEnclosure(retval + .getBytes(), quotId, quotId)); + } + + retTokens.add(tmpCat); + retTokens.add(retval); + return retTokens; + } + + public static final boolean isEmptyOrWhitespaceOnly(String str) { + if (str == null || str.length() == 0) { + return true; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return false; + } + } + + return true; + } + + public static String escapeQuote(String src, String quotChar) { + if (src == null) { + return null; + } + + src = StringUtils.toString(stripEnclosure(src.getBytes(), quotChar, quotChar)); + + int lastNdx = src.indexOf(quotChar); + String tmpSrc; + String tmpRest; + + tmpSrc = src.substring(0, lastNdx); + tmpSrc = tmpSrc + quotChar + quotChar; + + tmpRest = src.substring(lastNdx+1, src.length()); + + lastNdx = tmpRest.indexOf(quotChar); + while (lastNdx > -1) { + + tmpSrc = tmpSrc + tmpRest.substring(0, lastNdx); + tmpSrc = tmpSrc + quotChar + quotChar; + tmpRest = tmpRest.substring(lastNdx+1, tmpRest.length()); + + lastNdx = tmpRest.indexOf(quotChar); + } + + tmpSrc = tmpSrc + tmpRest; + src = tmpSrc; + + return src; + } + + /** + * Surrounds identifier with quoteChar and duplicates these symbols inside the identifier. + * + * @param quoteChar ` or " + * @param identifier in pedantic mode (connection property pedantic=true) identifier is treated as unquoted + * (as it is stored in the database) even if it starts and ends with quoteChar; + * in non-pedantic mode if identifier starts and ends with quoteChar method treats it as already quoted and doesn't modify. + * @param isPedantic are we in pedantic mode + * + * @return + * With quoteChar="`":
+ *
  • null -> null
  • + *
  • abc -> `abc`
  • + *
  • ab`c -> `ab``c`
  • + *
  • ab"c -> `ab"c`
  • + *
  • `ab``c` -> `ab``c` in non-pedantic mode or ```ab````c``` in pedantic mode
  • + * With quoteChar="\"":
    + *
  • null -> null
  • + *
  • abc -> "abc"
  • + *
  • ab`c -> "ab`c"
  • + *
  • ab"c -> "ab""c"
  • + *
  • "ab""c" -> "ab""c" in non-pedantic mode or """ab""""c""" in pedantic mode
  • + */ + public static String quoteIdentifier(String identifier, String quoteChar, boolean isPedantic) { + if (identifier == null) { + return null; + } + + if (!isPedantic && identifier.startsWith(quoteChar) && identifier.endsWith(quoteChar)) { + return identifier; + } + + return quoteChar + identifier.replaceAll(quoteChar, quoteChar+quoteChar) + quoteChar; + } + + /** + * Surrounds identifier with "`" and duplicates these symbols inside the identifier. + * + * @param identifier in pedantic mode (connection property pedantic=true) identifier is treated as unquoted + * (as it is stored in the database) even if it starts and ends with "`"; + * in non-pedantic mode if identifier starts and ends with "`" method treats it as already quoted and doesn't modify. + * @param isPedantic are we in pedantic mode + * + * @return + *
  • null -> null
  • + *
  • abc -> `abc`
  • + *
  • ab`c -> `ab``c`
  • + *
  • ab"c -> `ab"c`
  • + *
  • `ab``c` -> `ab``c` in non-pedantic mode or ```ab````c``` in pedantic mode
  • + */ + public static String quoteIdentifier(String identifier, boolean isPedantic) { + return quoteIdentifier(identifier, "`", isPedantic); + } + + /** + * Trims identifier, removes quote chars from first and last positions + * and replaces double occurrences of quote char from entire identifier, + * i.e converts quoted identifier into form as it is stored in database. + * + * @param identifier + * @param useAnsiQuotedIdentifiers should we check for " quotes too. + * @return + *
  • null -> null
  • + *
  • abc -> abc
  • + *
  • `abc` -> abc
  • + *
  • `ab``c` -> ab`c
  • + *
  • `"ab`c"` -> "ab`c"
  • + *
  • `ab"c` -> ab"c
  • + *
  • "abc" -> abc
  • + *
  • "`ab""c`" -> `ab"c`
  • + *
  • "ab`c" -> ab`c
  • + */ + public static String unQuoteIdentifier(String identifier, boolean useAnsiQuotedIdentifiers) { + if (identifier == null) { + return null; + } + + identifier = identifier.trim(); + + String quoteChar = null; + + // Backquotes are always valid identifier quotes + if (identifier.startsWith("`") && identifier.endsWith("`")) { + quoteChar = "`"; + } + + if (quoteChar== null && useAnsiQuotedIdentifiers) { + if (identifier.startsWith("\"") && identifier.endsWith("\"")) { + quoteChar = "\""; + } + } + + if (quoteChar != null) { + identifier = identifier.substring(1, (identifier.length() - 1)); + return identifier.replaceAll(quoteChar+quoteChar, quoteChar); + } + + return identifier; + } + + public static int indexOfQuoteDoubleAware(String line, String quoteChar, int startFrom) { + int lastIndex = line.length() -1; + + int beginPos = startFrom; + int pos = -1; + + boolean next = true; + while (next) { + pos = line.indexOf(quoteChar, beginPos); + if (pos == -1 || pos == lastIndex || !line.substring(pos+1).startsWith(quoteChar)) { + next = false; + } else { + beginPos = pos + 2; + } + } + + return pos; + } + + // The following methods all exist because of the Java bug + // + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 + // + // which has been observed by users and reported as MySQL Bug#61105 + // + // We can turn around and replace them with their java.lang.String + // equivalents if/when that bug is ever fixed. + + public static String toString(byte[] value, int offset, int length, + String encoding) throws UnsupportedEncodingException { + Charset cs = findCharset(encoding); + + return cs.decode(ByteBuffer.wrap(value, offset, length)).toString(); + } + + public static String toString(byte[] value, String encoding) + throws UnsupportedEncodingException { + Charset cs = findCharset(encoding); + + return cs.decode(ByteBuffer.wrap(value)).toString(); + } + + public static String toString(byte[] value, int offset, int length) { + try { + Charset cs = findCharset(platformEncoding); + + return cs.decode(ByteBuffer.wrap(value, offset, length)).toString(); + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + + public static String toString(byte[] value) { + try { + Charset cs = findCharset(platformEncoding); + + return cs.decode(ByteBuffer.wrap(value)).toString(); + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + + public static byte[] getBytes(char[] value) { + try { + return getBytes(value, 0, value.length, platformEncoding); + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + + public static byte[] getBytes(char[] value, int offset, int length) { + try { + return getBytes(value, offset, length, platformEncoding); + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + + public static byte[] getBytes(char[] value, String encoding) throws UnsupportedEncodingException { + return getBytes(value, 0, value.length, encoding); + } + + public static byte[] getBytes(char[] value, int offset, int length, String encoding) + throws UnsupportedEncodingException { + Charset cs = findCharset(encoding); + + ByteBuffer buf = cs.encode(CharBuffer.wrap(value, offset, length)); + + // can't simply .array() this to get the bytes + // especially with variable-length charsets the + // buffer is sometimes larger than the actual encoded data + int encodedLen = buf.limit(); + byte[] asBytes = new byte[encodedLen]; + buf.get(asBytes, 0, encodedLen); + + return asBytes; + } + + public static byte[] getBytes(String value) { + try { + return getBytes(value, 0, value.length(), platformEncoding); + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + + public static byte[] getBytes(String value, int offset, int length) { + try { + return getBytes(value, offset, length, platformEncoding); + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + + public static byte[] getBytes(String value, String encoding) throws UnsupportedEncodingException { + return getBytes(value, 0, value.length(), encoding); + } + + public static byte[] getBytes(String value, int offset, int length, String encoding) + throws UnsupportedEncodingException { + // Some CharsetEncoders (e.g. CP942, CP943, CP948, CP950, CP1381, CP1383, x-COMPOUND_TEXT or ISO-2022-JP) can't + // handle correctly when encoding directly from its methods while calling the encoder from String object works + // just fine. Most of these problems occur only in Java 1.5. + // CharsetEncoder#encode() may be used in Java 1.6+ but only the method that receives a char[] as argument as + // the one that receives a String argument doesn't always behaves correctly. + if (!Util.isJdbc4()) { + if (offset != 0 || length != value.length()) { + return value.substring(offset, offset + length).getBytes(encoding); + } + return value.getBytes(encoding); + } + + Charset cs = findCharset(encoding); + + ByteBuffer buf = cs.encode(CharBuffer.wrap(value.toCharArray(), offset, offset + length)); + + // can't simply .array() this to get the bytes + // especially with variable-length charsets the + // buffer is sometimes larger than the actual encoded data + int encodedLen = buf.limit(); + byte[] asBytes = new byte[encodedLen]; + buf.get(asBytes, 0, encodedLen); + + return asBytes; + } + + public static final boolean isValidIdChar(char c) { + return VALID_ID_CHARS.indexOf(c) != -1; + } + + private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', + 'e', 'f' }; + + public static void appendAsHex(StringBuilder builder, byte[] bytes) { + builder.append("0x"); + for (byte b : bytes) { + builder.append(HEX_DIGITS[(b >>> 4) & 0xF]).append(HEX_DIGITS[b & 0xF]); + } + } + + public static void appendAsHex(StringBuilder builder, int value) { + if (value == 0) { + builder.append("0x0"); + return; + } + + int shift = 32; + byte nibble; + boolean nonZeroFound = false; + + builder.append("0x"); + do { + shift -= 4; + nibble = (byte) ((value >>> shift) & 0xF); + if (nonZeroFound) { + builder.append(HEX_DIGITS[nibble]); + } else if (nibble != 0) { + builder.append(HEX_DIGITS[nibble]); + nonZeroFound = true; + } + } while (shift != 0); + } + + public static byte[] getBytesNullTerminated(String value) { + try { + Charset cs = findCharset(platformEncoding); + ByteBuffer buf = cs.encode(value); + int encodedLen = buf.limit(); + byte[] asBytes = new byte[encodedLen+1]; + buf.get(asBytes, 0, encodedLen); + asBytes[encodedLen] = 0; + + return asBytes; + } catch (UnsupportedEncodingException e) { + // can't happen, emulating new String(byte[]) + } + + return null; + } + } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/TimeUtil.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/TimeUtil.java (.../TimeUtil.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/TimeUtil.java (.../TimeUtil.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,39 +1,37 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.sql.Date; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; - import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; import java.util.HashMap; -import java.util.Locale; +import java.util.Iterator; import java.util.Map; import java.util.TimeZone; @@ -43,220 +41,230 @@ * @author Mark Matthews */ public class TimeUtil { - static final Map ABBREVIATED_TIMEZONES; + static final Map ABBREVIATED_TIMEZONES; static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); - static final Map TIMEZONE_MAPPINGS; + static final Map TIMEZONE_MAPPINGS; static { - HashMap tempMap = new HashMap(); + HashMap tempTzMap = new HashMap(); // // Windows Mappings // - tempMap.put("Romance", "Europe/Paris"); - tempMap.put("Romance Standard Time", "Europe/Paris"); - tempMap.put("Warsaw", "Europe/Warsaw"); - tempMap.put("Central Europe", "Europe/Prague"); - tempMap.put("Central Europe Standard Time", "Europe/Prague"); - tempMap.put("Prague Bratislava", "Europe/Prague"); - tempMap.put("W. Central Africa Standard Time", "Africa/Luanda"); - tempMap.put("FLE", "Europe/Helsinki"); - tempMap.put("FLE Standard Time", "Europe/Helsinki"); - tempMap.put("GFT", "Europe/Athens"); - tempMap.put("GFT Standard Time", "Europe/Athens"); - tempMap.put("GTB", "Europe/Athens"); - tempMap.put("GTB Standard Time", "Europe/Athens"); - tempMap.put("Israel", "Asia/Jerusalem"); - tempMap.put("Israel Standard Time", "Asia/Jerusalem"); - tempMap.put("Arab", "Asia/Riyadh"); - tempMap.put("Arab Standard Time", "Asia/Riyadh"); - tempMap.put("Arabic Standard Time", "Asia/Baghdad"); - tempMap.put("E. Africa", "Africa/Nairobi"); - tempMap.put("E. Africa Standard Time", "Africa/Nairobi"); - tempMap.put("Saudi Arabia", "Asia/Riyadh"); - tempMap.put("Saudi Arabia Standard Time", "Asia/Riyadh"); - tempMap.put("Iran", "Asia/Tehran"); - tempMap.put("Iran Standard Time", "Asia/Tehran"); - tempMap.put("Afghanistan", "Asia/Kabul"); - tempMap.put("Afghanistan Standard Time", "Asia/Kabul"); - tempMap.put("India", "Asia/Calcutta"); - tempMap.put("India Standard Time", "Asia/Calcutta"); - tempMap.put("Myanmar Standard Time", "Asia/Rangoon"); - tempMap.put("Nepal Standard Time", "Asia/Katmandu"); - tempMap.put("Sri Lanka", "Asia/Colombo"); - tempMap.put("Sri Lanka Standard Time", "Asia/Colombo"); - tempMap.put("Beijing", "Asia/Shanghai"); - tempMap.put("China", "Asia/Shanghai"); - tempMap.put("China Standard Time", "Asia/Shanghai"); - tempMap.put("AUS Central", "Australia/Darwin"); - tempMap.put("AUS Central Standard Time", "Australia/Darwin"); - tempMap.put("Cen. Australia", "Australia/Adelaide"); - tempMap.put("Cen. Australia Standard Time", "Australia/Adelaide"); - tempMap.put("Vladivostok", "Asia/Vladivostok"); - tempMap.put("Vladivostok Standard Time", "Asia/Vladivostok"); - tempMap.put("West Pacific", "Pacific/Guam"); - tempMap.put("West Pacific Standard Time", "Pacific/Guam"); - tempMap.put("E. South America", "America/Sao_Paulo"); - tempMap.put("E. South America Standard Time", "America/Sao_Paulo"); - tempMap.put("Greenland Standard Time", "America/Godthab"); - tempMap.put("Newfoundland", "America/St_Johns"); - tempMap.put("Newfoundland Standard Time", "America/St_Johns"); - tempMap.put("Pacific SA", "America/Caracas"); - tempMap.put("Pacific SA Standard Time", "America/Caracas"); - tempMap.put("SA Western", "America/Caracas"); - tempMap.put("SA Western Standard Time", "America/Caracas"); - tempMap.put("SA Pacific", "America/Bogota"); - tempMap.put("SA Pacific Standard Time", "America/Bogota"); - tempMap.put("US Eastern", "America/Indianapolis"); - tempMap.put("US Eastern Standard Time", "America/Indianapolis"); - tempMap.put("Central America Standard Time", "America/Regina"); - tempMap.put("Mexico", "America/Mexico_City"); - tempMap.put("Mexico Standard Time", "America/Mexico_City"); - tempMap.put("Canada Central", "America/Regina"); - tempMap.put("Canada Central Standard Time", "America/Regina"); - tempMap.put("US Mountain", "America/Phoenix"); - tempMap.put("US Mountain Standard Time", "America/Phoenix"); - tempMap.put("GMT", "Europe/London"); - tempMap.put("GMT Standard Time", "Europe/London"); - tempMap.put("Ekaterinburg", "Asia/Yekaterinburg"); - tempMap.put("Ekaterinburg Standard Time", "Asia/Yekaterinburg"); - tempMap.put("West Asia", "Asia/Karachi"); - tempMap.put("West Asia Standard Time", "Asia/Karachi"); - tempMap.put("Central Asia", "Asia/Dhaka"); - tempMap.put("Central Asia Standard Time", "Asia/Dhaka"); - tempMap.put("N. Central Asia Standard Time", "Asia/Novosibirsk"); - tempMap.put("Bangkok", "Asia/Bangkok"); - tempMap.put("Bangkok Standard Time", "Asia/Bangkok"); - tempMap.put("North Asia Standard Time", "Asia/Krasnoyarsk"); - tempMap.put("SE Asia", "Asia/Bangkok"); - tempMap.put("SE Asia Standard Time", "Asia/Bangkok"); - tempMap.put("North Asia East Standard Time", "Asia/Ulaanbaatar"); - tempMap.put("Singapore", "Asia/Singapore"); - tempMap.put("Singapore Standard Time", "Asia/Singapore"); - tempMap.put("Taipei", "Asia/Taipei"); - tempMap.put("Taipei Standard Time", "Asia/Taipei"); - tempMap.put("W. Australia", "Australia/Perth"); - tempMap.put("W. Australia Standard Time", "Australia/Perth"); - tempMap.put("Korea", "Asia/Seoul"); - tempMap.put("Korea Standard Time", "Asia/Seoul"); - tempMap.put("Tokyo", "Asia/Tokyo"); - tempMap.put("Tokyo Standard Time", "Asia/Tokyo"); - tempMap.put("Yakutsk", "Asia/Yakutsk"); - tempMap.put("Yakutsk Standard Time", "Asia/Yakutsk"); - tempMap.put("Central European", "Europe/Belgrade"); - tempMap.put("Central European Standard Time", "Europe/Belgrade"); - tempMap.put("W. Europe", "Europe/Berlin"); - tempMap.put("W. Europe Standard Time", "Europe/Berlin"); - tempMap.put("Tasmania", "Australia/Hobart"); - tempMap.put("Tasmania Standard Time", "Australia/Hobart"); - tempMap.put("AUS Eastern", "Australia/Sydney"); - tempMap.put("AUS Eastern Standard Time", "Australia/Sydney"); - tempMap.put("E. Australia", "Australia/Brisbane"); - tempMap.put("E. Australia Standard Time", "Australia/Brisbane"); - tempMap.put("Sydney Standard Time", "Australia/Sydney"); - tempMap.put("Central Pacific", "Pacific/Guadalcanal"); - tempMap.put("Central Pacific Standard Time", "Pacific/Guadalcanal"); - tempMap.put("Dateline", "Pacific/Majuro"); - tempMap.put("Dateline Standard Time", "Pacific/Majuro"); - tempMap.put("Fiji", "Pacific/Fiji"); - tempMap.put("Fiji Standard Time", "Pacific/Fiji"); - tempMap.put("Samoa", "Pacific/Apia"); - tempMap.put("Samoa Standard Time", "Pacific/Apia"); - tempMap.put("Hawaiian", "Pacific/Honolulu"); - tempMap.put("Hawaiian Standard Time", "Pacific/Honolulu"); - tempMap.put("Alaskan", "America/Anchorage"); - tempMap.put("Alaskan Standard Time", "America/Anchorage"); - tempMap.put("Pacific", "America/Los_Angeles"); - tempMap.put("Pacific Standard Time", "America/Los_Angeles"); - tempMap.put("Mexico Standard Time 2", "America/Chihuahua"); - tempMap.put("Mountain", "America/Denver"); - tempMap.put("Mountain Standard Time", "America/Denver"); - tempMap.put("Central", "America/Chicago"); - tempMap.put("Central Standard Time", "America/Chicago"); - tempMap.put("Eastern", "America/New_York"); - tempMap.put("Eastern Standard Time", "America/New_York"); - tempMap.put("E. Europe", "Europe/Bucharest"); - tempMap.put("E. Europe Standard Time", "Europe/Bucharest"); - tempMap.put("Egypt", "Africa/Cairo"); - tempMap.put("Egypt Standard Time", "Africa/Cairo"); - tempMap.put("South Africa", "Africa/Harare"); - tempMap.put("South Africa Standard Time", "Africa/Harare"); - tempMap.put("Atlantic", "America/Halifax"); - tempMap.put("Atlantic Standard Time", "America/Halifax"); - tempMap.put("SA Eastern", "America/Buenos_Aires"); - tempMap.put("SA Eastern Standard Time", "America/Buenos_Aires"); - tempMap.put("Mid-Atlantic", "Atlantic/South_Georgia"); - tempMap.put("Mid-Atlantic Standard Time", "Atlantic/South_Georgia"); - tempMap.put("Azores", "Atlantic/Azores"); - tempMap.put("Azores Standard Time", "Atlantic/Azores"); - tempMap.put("Cape Verde Standard Time", "Atlantic/Cape_Verde"); - tempMap.put("Russian", "Europe/Moscow"); - tempMap.put("Russian Standard Time", "Europe/Moscow"); - tempMap.put("New Zealand", "Pacific/Auckland"); - tempMap.put("New Zealand Standard Time", "Pacific/Auckland"); - tempMap.put("Tonga Standard Time", "Pacific/Tongatapu"); - tempMap.put("Arabian", "Asia/Muscat"); - tempMap.put("Arabian Standard Time", "Asia/Muscat"); - tempMap.put("Caucasus", "Asia/Tbilisi"); - tempMap.put("Caucasus Standard Time", "Asia/Tbilisi"); - tempMap.put("GMT Standard Time", "GMT"); - tempMap.put("Greenwich", "GMT"); - tempMap.put("Greenwich Standard Time", "GMT"); - tempMap.put("UTC", "GMT"); + tempTzMap.put("Romance", "Europe/Paris"); + tempTzMap.put("Romance Standard Time", "Europe/Paris"); + tempTzMap.put("Warsaw", "Europe/Warsaw"); + tempTzMap.put("Central Europe", "Europe/Prague"); + tempTzMap.put("Central Europe Standard Time", "Europe/Prague"); + tempTzMap.put("Prague Bratislava", "Europe/Prague"); + tempTzMap.put("W. Central Africa Standard Time", "Africa/Luanda"); + tempTzMap.put("FLE", "Europe/Helsinki"); + tempTzMap.put("FLE Standard Time", "Europe/Helsinki"); + tempTzMap.put("GFT", "Europe/Athens"); + tempTzMap.put("GFT Standard Time", "Europe/Athens"); + tempTzMap.put("GTB", "Europe/Athens"); + tempTzMap.put("GTB Standard Time", "Europe/Athens"); + tempTzMap.put("Israel", "Asia/Jerusalem"); + tempTzMap.put("Israel Standard Time", "Asia/Jerusalem"); + tempTzMap.put("Arab", "Asia/Riyadh"); + tempTzMap.put("Arab Standard Time", "Asia/Riyadh"); + tempTzMap.put("Arabic Standard Time", "Asia/Baghdad"); + tempTzMap.put("E. Africa", "Africa/Nairobi"); + tempTzMap.put("E. Africa Standard Time", "Africa/Nairobi"); + tempTzMap.put("Saudi Arabia", "Asia/Riyadh"); + tempTzMap.put("Saudi Arabia Standard Time", "Asia/Riyadh"); + tempTzMap.put("Iran", "Asia/Tehran"); + tempTzMap.put("Iran Standard Time", "Asia/Tehran"); + tempTzMap.put("Afghanistan", "Asia/Kabul"); + tempTzMap.put("Afghanistan Standard Time", "Asia/Kabul"); + tempTzMap.put("India", "Asia/Calcutta"); + tempTzMap.put("India Standard Time", "Asia/Calcutta"); + tempTzMap.put("Myanmar Standard Time", "Asia/Rangoon"); + tempTzMap.put("Nepal Standard Time", "Asia/Katmandu"); + tempTzMap.put("Sri Lanka", "Asia/Colombo"); + tempTzMap.put("Sri Lanka Standard Time", "Asia/Colombo"); + tempTzMap.put("Beijing", "Asia/Shanghai"); + tempTzMap.put("China", "Asia/Shanghai"); + tempTzMap.put("China Standard Time", "Asia/Shanghai"); + tempTzMap.put("AUS Central", "Australia/Darwin"); + tempTzMap.put("AUS Central Standard Time", "Australia/Darwin"); + tempTzMap.put("Cen. Australia", "Australia/Adelaide"); + tempTzMap.put("Cen. Australia Standard Time", "Australia/Adelaide"); + tempTzMap.put("Vladivostok", "Asia/Vladivostok"); + tempTzMap.put("Vladivostok Standard Time", "Asia/Vladivostok"); + tempTzMap.put("West Pacific", "Pacific/Guam"); + tempTzMap.put("West Pacific Standard Time", "Pacific/Guam"); + tempTzMap.put("E. South America", "America/Sao_Paulo"); + tempTzMap.put("E. South America Standard Time", "America/Sao_Paulo"); + tempTzMap.put("Greenland Standard Time", "America/Godthab"); + tempTzMap.put("Newfoundland", "America/St_Johns"); + tempTzMap.put("Newfoundland Standard Time", "America/St_Johns"); + tempTzMap.put("Pacific SA", "America/Caracas"); + tempTzMap.put("Pacific SA Standard Time", "America/Caracas"); + tempTzMap.put("SA Western", "America/Caracas"); + tempTzMap.put("SA Western Standard Time", "America/Caracas"); + tempTzMap.put("SA Pacific", "America/Bogota"); + tempTzMap.put("SA Pacific Standard Time", "America/Bogota"); + tempTzMap.put("US Eastern", "America/Indianapolis"); + tempTzMap.put("US Eastern Standard Time", "America/Indianapolis"); + tempTzMap.put("Central America Standard Time", "America/Regina"); + tempTzMap.put("Mexico", "America/Mexico_City"); + tempTzMap.put("Mexico Standard Time", "America/Mexico_City"); + tempTzMap.put("Canada Central", "America/Regina"); + tempTzMap.put("Canada Central Standard Time", "America/Regina"); + tempTzMap.put("US Mountain", "America/Phoenix"); + tempTzMap.put("US Mountain Standard Time", "America/Phoenix"); + tempTzMap.put("GMT", "GMT"); + tempTzMap.put("Ekaterinburg", "Asia/Yekaterinburg"); + tempTzMap.put("Ekaterinburg Standard Time", "Asia/Yekaterinburg"); + tempTzMap.put("West Asia", "Asia/Karachi"); + tempTzMap.put("West Asia Standard Time", "Asia/Karachi"); + tempTzMap.put("Central Asia", "Asia/Dhaka"); + tempTzMap.put("Central Asia Standard Time", "Asia/Dhaka"); + tempTzMap.put("N. Central Asia Standard Time", "Asia/Novosibirsk"); + tempTzMap.put("Bangkok", "Asia/Bangkok"); + tempTzMap.put("Bangkok Standard Time", "Asia/Bangkok"); + tempTzMap.put("North Asia Standard Time", "Asia/Krasnoyarsk"); + tempTzMap.put("SE Asia", "Asia/Bangkok"); + tempTzMap.put("SE Asia Standard Time", "Asia/Bangkok"); + tempTzMap.put("North Asia East Standard Time", "Asia/Ulaanbaatar"); + tempTzMap.put("Singapore", "Asia/Singapore"); + tempTzMap.put("Singapore Standard Time", "Asia/Singapore"); + tempTzMap.put("Taipei", "Asia/Taipei"); + tempTzMap.put("Taipei Standard Time", "Asia/Taipei"); + tempTzMap.put("W. Australia", "Australia/Perth"); + tempTzMap.put("W. Australia Standard Time", "Australia/Perth"); + tempTzMap.put("Korea", "Asia/Seoul"); + tempTzMap.put("Korea Standard Time", "Asia/Seoul"); + tempTzMap.put("Tokyo", "Asia/Tokyo"); + tempTzMap.put("Tokyo Standard Time", "Asia/Tokyo"); + tempTzMap.put("Yakutsk", "Asia/Yakutsk"); + tempTzMap.put("Yakutsk Standard Time", "Asia/Yakutsk"); + tempTzMap.put("Central European", "Europe/Belgrade"); + tempTzMap.put("Central European Standard Time", "Europe/Belgrade"); + tempTzMap.put("W. Europe", "Europe/Berlin"); + tempTzMap.put("W. Europe Standard Time", "Europe/Berlin"); + tempTzMap.put("Tasmania", "Australia/Hobart"); + tempTzMap.put("Tasmania Standard Time", "Australia/Hobart"); + tempTzMap.put("AUS Eastern", "Australia/Sydney"); + tempTzMap.put("AUS Eastern Standard Time", "Australia/Sydney"); + tempTzMap.put("E. Australia", "Australia/Brisbane"); + tempTzMap.put("E. Australia Standard Time", "Australia/Brisbane"); + tempTzMap.put("Sydney Standard Time", "Australia/Sydney"); + tempTzMap.put("Central Pacific", "Pacific/Guadalcanal"); + tempTzMap.put("Central Pacific Standard Time", "Pacific/Guadalcanal"); + tempTzMap.put("Dateline", "Pacific/Majuro"); + tempTzMap.put("Dateline Standard Time", "Pacific/Majuro"); + tempTzMap.put("Fiji", "Pacific/Fiji"); + tempTzMap.put("Fiji Standard Time", "Pacific/Fiji"); + tempTzMap.put("Samoa", "Pacific/Apia"); + tempTzMap.put("Samoa Standard Time", "Pacific/Apia"); + tempTzMap.put("Hawaiian", "Pacific/Honolulu"); + tempTzMap.put("Hawaiian Standard Time", "Pacific/Honolulu"); + tempTzMap.put("Alaskan", "America/Anchorage"); + tempTzMap.put("Alaskan Standard Time", "America/Anchorage"); + tempTzMap.put("Pacific", "America/Los_Angeles"); + tempTzMap.put("Pacific Standard Time", "America/Los_Angeles"); + tempTzMap.put("Mexico Standard Time 2", "America/Chihuahua"); + tempTzMap.put("Mountain", "America/Denver"); + tempTzMap.put("Mountain Standard Time", "America/Denver"); + tempTzMap.put("Central", "America/Chicago"); + tempTzMap.put("Central Standard Time", "America/Chicago"); + tempTzMap.put("Eastern", "America/New_York"); + tempTzMap.put("Eastern Standard Time", "America/New_York"); + tempTzMap.put("E. Europe", "Europe/Bucharest"); + tempTzMap.put("E. Europe Standard Time", "Europe/Bucharest"); + tempTzMap.put("Egypt", "Africa/Cairo"); + tempTzMap.put("Egypt Standard Time", "Africa/Cairo"); + tempTzMap.put("South Africa", "Africa/Harare"); + tempTzMap.put("South Africa Standard Time", "Africa/Harare"); + tempTzMap.put("Atlantic", "America/Halifax"); + tempTzMap.put("Atlantic Standard Time", "America/Halifax"); + tempTzMap.put("SA Eastern", "America/Buenos_Aires"); + tempTzMap.put("SA Eastern Standard Time", "America/Buenos_Aires"); + tempTzMap.put("Mid-Atlantic", "Atlantic/South_Georgia"); + tempTzMap.put("Mid-Atlantic Standard Time", "Atlantic/South_Georgia"); + tempTzMap.put("Azores", "Atlantic/Azores"); + tempTzMap.put("Azores Standard Time", "Atlantic/Azores"); + tempTzMap.put("Cape Verde Standard Time", "Atlantic/Cape_Verde"); + tempTzMap.put("Russian", "Europe/Moscow"); + tempTzMap.put("Russian Standard Time", "Europe/Moscow"); + tempTzMap.put("New Zealand", "Pacific/Auckland"); + tempTzMap.put("New Zealand Standard Time", "Pacific/Auckland"); + tempTzMap.put("Tonga Standard Time", "Pacific/Tongatapu"); + tempTzMap.put("Arabian", "Asia/Muscat"); + tempTzMap.put("Arabian Standard Time", "Asia/Muscat"); + tempTzMap.put("Caucasus", "Asia/Tbilisi"); + tempTzMap.put("Caucasus Standard Time", "Asia/Tbilisi"); + tempTzMap.put("GMT Standard Time", "GMT"); + tempTzMap.put("Greenwich", "GMT"); + tempTzMap.put("Greenwich Standard Time", "GMT"); + tempTzMap.put("UTC", "GMT"); - TIMEZONE_MAPPINGS = Collections.unmodifiableMap(tempMap); + // MySQL understands the Continent/City/region as well + Iterator> entries = tempTzMap.entrySet().iterator(); + Map entryMap = new HashMap(tempTzMap.size()); // to avoid ConcurrentModificationException + + while (entries.hasNext()) { + String name = entries.next().getValue(); + entryMap.put(name, name); + } + + tempTzMap.putAll(entryMap); + + TIMEZONE_MAPPINGS = Collections.unmodifiableMap(tempTzMap); // // Handle abbreviated mappings // - tempMap = new HashMap(); + HashMap tempAbbrMap = new HashMap(); - tempMap.put("ACST", new String[] { "America/Porto_Acre" }); - tempMap.put("ACT", new String[] { "America/Porto_Acre" }); - tempMap.put("ADDT", new String[] { "America/Pangnirtung" }); - tempMap.put("ADMT", new String[] { "Africa/Asmera", + tempAbbrMap.put("ACST", new String[] { "America/Porto_Acre" }); + tempAbbrMap.put("ACT", new String[] { "America/Porto_Acre" }); + tempAbbrMap.put("ADDT", new String[] { "America/Pangnirtung" }); + tempAbbrMap.put("ADMT", new String[] { "Africa/Asmera", "Africa/Addis_Ababa" }); - tempMap.put("ADT", new String[] { "Atlantic/Bermuda", "Asia/Baghdad", + tempAbbrMap.put("ADT", new String[] { "Atlantic/Bermuda", "Asia/Baghdad", "America/Thule", "America/Goose_Bay", "America/Halifax", "America/Glace_Bay", "America/Pangnirtung", "America/Barbados", "America/Martinique" }); - tempMap.put("AFT", new String[] { "Asia/Kabul" }); - tempMap.put("AHDT", new String[] { "America/Anchorage" }); - tempMap.put("AHST", new String[] { "America/Anchorage" }); - tempMap.put("AHWT", new String[] { "America/Anchorage" }); - tempMap.put("AKDT", new String[] { "America/Juneau", "America/Yakutat", + tempAbbrMap.put("AFT", new String[] { "Asia/Kabul" }); + tempAbbrMap.put("AHDT", new String[] { "America/Anchorage" }); + tempAbbrMap.put("AHST", new String[] { "America/Anchorage" }); + tempAbbrMap.put("AHWT", new String[] { "America/Anchorage" }); + tempAbbrMap.put("AKDT", new String[] { "America/Juneau", "America/Yakutat", "America/Anchorage", "America/Nome" }); - tempMap.put("AKST", new String[] { "Asia/Aqtobe", "America/Juneau", + tempAbbrMap.put("AKST", new String[] { "Asia/Aqtobe", "America/Juneau", "America/Yakutat", "America/Anchorage", "America/Nome" }); - tempMap.put("AKT", new String[] { "Asia/Aqtobe" }); - tempMap.put("AKTST", new String[] { "Asia/Aqtobe" }); - tempMap.put("AKWT", new String[] { "America/Juneau", "America/Yakutat", + tempAbbrMap.put("AKT", new String[] { "Asia/Aqtobe" }); + tempAbbrMap.put("AKTST", new String[] { "Asia/Aqtobe" }); + tempAbbrMap.put("AKWT", new String[] { "America/Juneau", "America/Yakutat", "America/Anchorage", "America/Nome" }); - tempMap.put("ALMST", new String[] { "Asia/Almaty" }); - tempMap.put("ALMT", new String[] { "Asia/Almaty" }); - tempMap.put("AMST", new String[] { "Asia/Yerevan", "America/Cuiaba", + tempAbbrMap.put("ALMST", new String[] { "Asia/Almaty" }); + tempAbbrMap.put("ALMT", new String[] { "Asia/Almaty" }); + tempAbbrMap.put("AMST", new String[] { "Asia/Yerevan", "America/Cuiaba", "America/Porto_Velho", "America/Boa_Vista", "America/Manaus" }); - tempMap.put("AMT", new String[] { "Europe/Athens", "Europe/Amsterdam", + tempAbbrMap.put("AMT", new String[] { "Europe/Athens", "Europe/Amsterdam", "Asia/Yerevan", "Africa/Asmera", "America/Cuiaba", "America/Porto_Velho", "America/Boa_Vista", "America/Manaus", "America/Asuncion" }); - tempMap.put("ANAMT", new String[] { "Asia/Anadyr" }); - tempMap.put("ANAST", new String[] { "Asia/Anadyr" }); - tempMap.put("ANAT", new String[] { "Asia/Anadyr" }); - tempMap.put("ANT", new String[] { "America/Aruba", "America/Curacao" }); - tempMap.put("AQTST", new String[] { "Asia/Aqtobe", "Asia/Aqtau" }); - tempMap.put("AQTT", new String[] { "Asia/Aqtobe", "Asia/Aqtau" }); - tempMap.put("ARST", new String[] { "Antarctica/Palmer", + tempAbbrMap.put("ANAMT", new String[] { "Asia/Anadyr" }); + tempAbbrMap.put("ANAST", new String[] { "Asia/Anadyr" }); + tempAbbrMap.put("ANAT", new String[] { "Asia/Anadyr" }); + tempAbbrMap.put("ANT", new String[] { "America/Aruba", "America/Curacao" }); + tempAbbrMap.put("AQTST", new String[] { "Asia/Aqtobe", "Asia/Aqtau" }); + tempAbbrMap.put("AQTT", new String[] { "Asia/Aqtobe", "Asia/Aqtau" }); + tempAbbrMap.put("ARST", new String[] { "Antarctica/Palmer", "America/Buenos_Aires", "America/Rosario", "America/Cordoba", "America/Jujuy", "America/Catamarca", "America/Mendoza" }); - tempMap.put("ART", new String[] { "Antarctica/Palmer", + tempAbbrMap.put("ART", new String[] { "Antarctica/Palmer", "America/Buenos_Aires", "America/Rosario", "America/Cordoba", "America/Jujuy", "America/Catamarca", "America/Mendoza" }); - tempMap.put("ASHST", new String[] { "Asia/Ashkhabad" }); - tempMap.put("ASHT", new String[] { "Asia/Ashkhabad" }); - tempMap.put("AST", new String[] { "Atlantic/Bermuda", "Asia/Bahrain", + tempAbbrMap.put("ASHST", new String[] { "Asia/Ashkhabad" }); + tempAbbrMap.put("ASHT", new String[] { "Asia/Ashkhabad" }); + tempAbbrMap.put("AST", new String[] { "Atlantic/Bermuda", "Asia/Bahrain", "Asia/Baghdad", "Asia/Kuwait", "Asia/Qatar", "Asia/Riyadh", "Asia/Aden", "America/Thule", "America/Goose_Bay", "America/Halifax", "America/Glace_Bay", "America/Pangnirtung", @@ -267,51 +275,51 @@ "America/St_Kitts", "America/St_Lucia", "America/Miquelon", "America/St_Vincent", "America/Tortola", "America/St_Thomas", "America/Aruba", "America/Curacao", "America/Port_of_Spain" }); - tempMap.put("AWT", new String[] { "America/Puerto_Rico" }); - tempMap.put("AZOST", new String[] { "Atlantic/Azores" }); - tempMap.put("AZOT", new String[] { "Atlantic/Azores" }); - tempMap.put("AZST", new String[] { "Asia/Baku" }); - tempMap.put("AZT", new String[] { "Asia/Baku" }); - tempMap.put("BAKST", new String[] { "Asia/Baku" }); - tempMap.put("BAKT", new String[] { "Asia/Baku" }); - tempMap.put("BDT", new String[] { "Asia/Dacca", "America/Nome", + tempAbbrMap.put("AWT", new String[] { "America/Puerto_Rico" }); + tempAbbrMap.put("AZOST", new String[] { "Atlantic/Azores" }); + tempAbbrMap.put("AZOT", new String[] { "Atlantic/Azores" }); + tempAbbrMap.put("AZST", new String[] { "Asia/Baku" }); + tempAbbrMap.put("AZT", new String[] { "Asia/Baku" }); + tempAbbrMap.put("BAKST", new String[] { "Asia/Baku" }); + tempAbbrMap.put("BAKT", new String[] { "Asia/Baku" }); + tempAbbrMap.put("BDT", new String[] { "Asia/Dacca", "America/Nome", "America/Adak" }); - tempMap.put("BEAT", new String[] { "Africa/Nairobi", + tempAbbrMap.put("BEAT", new String[] { "Africa/Nairobi", "Africa/Mogadishu", "Africa/Kampala" }); - tempMap.put("BEAUT", new String[] { "Africa/Nairobi", + tempAbbrMap.put("BEAUT", new String[] { "Africa/Nairobi", "Africa/Dar_es_Salaam", "Africa/Kampala" }); - tempMap.put("BMT", new String[] { "Europe/Brussels", "Europe/Chisinau", + tempAbbrMap.put("BMT", new String[] { "Europe/Brussels", "Europe/Chisinau", "Europe/Tiraspol", "Europe/Bucharest", "Europe/Zurich", "Asia/Baghdad", "Asia/Bangkok", "Africa/Banjul", "America/Barbados", "America/Bogota" }); - tempMap.put("BNT", new String[] { "Asia/Brunei" }); - tempMap.put("BORT", + tempAbbrMap.put("BNT", new String[] { "Asia/Brunei" }); + tempAbbrMap.put("BORT", new String[] { "Asia/Ujung_Pandang", "Asia/Kuching" }); - tempMap.put("BOST", new String[] { "America/La_Paz" }); - tempMap.put("BOT", new String[] { "America/La_Paz" }); - tempMap.put("BRST", new String[] { "America/Belem", + tempAbbrMap.put("BOST", new String[] { "America/La_Paz" }); + tempAbbrMap.put("BOT", new String[] { "America/La_Paz" }); + tempAbbrMap.put("BRST", new String[] { "America/Belem", "America/Fortaleza", "America/Araguaina", "America/Maceio", "America/Sao_Paulo" }); - tempMap.put("BRT", new String[] { "America/Belem", "America/Fortaleza", + tempAbbrMap.put("BRT", new String[] { "America/Belem", "America/Fortaleza", "America/Araguaina", "America/Maceio", "America/Sao_Paulo" }); - tempMap.put("BST", new String[] { "Europe/London", "Europe/Belfast", + tempAbbrMap.put("BST", new String[] { "Europe/London", "Europe/Belfast", "Europe/Dublin", "Europe/Gibraltar", "Pacific/Pago_Pago", "Pacific/Midway", "America/Nome", "America/Adak" }); - tempMap.put("BTT", new String[] { "Asia/Thimbu" }); - tempMap.put("BURT", new String[] { "Asia/Dacca", "Asia/Rangoon", + tempAbbrMap.put("BTT", new String[] { "Asia/Thimbu" }); + tempAbbrMap.put("BURT", new String[] { "Asia/Dacca", "Asia/Rangoon", "Asia/Calcutta" }); - tempMap.put("BWT", new String[] { "America/Nome", "America/Adak" }); - tempMap.put("CANT", new String[] { "Atlantic/Canary" }); - tempMap.put("CAST", + tempAbbrMap.put("BWT", new String[] { "America/Nome", "America/Adak" }); + tempAbbrMap.put("CANT", new String[] { "Atlantic/Canary" }); + tempAbbrMap.put("CAST", new String[] { "Africa/Gaborone", "Africa/Khartoum" }); - tempMap.put("CAT", new String[] { "Africa/Gaborone", + tempAbbrMap.put("CAT", new String[] { "Africa/Gaborone", "Africa/Bujumbura", "Africa/Lubumbashi", "Africa/Blantyre", "Africa/Maputo", "Africa/Windhoek", "Africa/Kigali", "Africa/Khartoum", "Africa/Lusaka", "Africa/Harare", "America/Anchorage" }); - tempMap.put("CCT", new String[] { "Indian/Cocos" }); - tempMap.put("CDDT", new String[] { "America/Rankin_Inlet" }); - tempMap.put("CDT", new String[] { "Asia/Harbin", "Asia/Shanghai", + tempAbbrMap.put("CCT", new String[] { "Indian/Cocos" }); + tempAbbrMap.put("CDDT", new String[] { "America/Rankin_Inlet" }); + tempAbbrMap.put("CDT", new String[] { "Asia/Harbin", "Asia/Shanghai", "Asia/Chungking", "Asia/Urumqi", "Asia/Kashgar", "Asia/Taipei", "Asia/Macao", "America/Chicago", "America/Indianapolis", "America/Indiana/Marengo", "America/Indiana/Knox", @@ -323,7 +331,7 @@ "America/Belize", "America/Costa_Rica", "America/Havana", "America/El_Salvador", "America/Guatemala", "America/Tegucigalpa", "America/Managua" }); - tempMap.put("CEST", new String[] { "Europe/Tirane", "Europe/Andorra", + tempAbbrMap.put("CEST", new String[] { "Europe/Tirane", "Europe/Andorra", "Europe/Vienna", "Europe/Minsk", "Europe/Brussels", "Europe/Sofia", "Europe/Prague", "Europe/Copenhagen", "Europe/Tallinn", "Europe/Berlin", "Europe/Gibraltar", @@ -337,7 +345,7 @@ "Europe/Zaporozhye", "Europe/Simferopol", "Europe/Belgrade", "Africa/Algiers", "Africa/Tripoli", "Africa/Tunis", "Africa/Ceuta" }); - tempMap.put("CET", new String[] { "Europe/Tirane", "Europe/Andorra", + tempAbbrMap.put("CET", new String[] { "Europe/Tirane", "Europe/Andorra", "Europe/Vienna", "Europe/Minsk", "Europe/Brussels", "Europe/Sofia", "Europe/Prague", "Europe/Copenhagen", "Europe/Tallinn", "Europe/Berlin", "Europe/Gibraltar", @@ -351,25 +359,25 @@ "Europe/Zaporozhye", "Europe/Simferopol", "Europe/Belgrade", "Africa/Algiers", "Africa/Tripoli", "Africa/Casablanca", "Africa/Tunis", "Africa/Ceuta" }); - tempMap.put("CGST", new String[] { "America/Scoresbysund" }); - tempMap.put("CGT", new String[] { "America/Scoresbysund" }); - tempMap.put("CHDT", new String[] { "America/Belize" }); - tempMap.put("CHUT", new String[] { "Asia/Chungking" }); - tempMap.put("CJT", new String[] { "Asia/Tokyo" }); - tempMap.put("CKHST", new String[] { "Pacific/Rarotonga" }); - tempMap.put("CKT", new String[] { "Pacific/Rarotonga" }); - tempMap.put("CLST", new String[] { "Antarctica/Palmer", + tempAbbrMap.put("CGST", new String[] { "America/Scoresbysund" }); + tempAbbrMap.put("CGT", new String[] { "America/Scoresbysund" }); + tempAbbrMap.put("CHDT", new String[] { "America/Belize" }); + tempAbbrMap.put("CHUT", new String[] { "Asia/Chungking" }); + tempAbbrMap.put("CJT", new String[] { "Asia/Tokyo" }); + tempAbbrMap.put("CKHST", new String[] { "Pacific/Rarotonga" }); + tempAbbrMap.put("CKT", new String[] { "Pacific/Rarotonga" }); + tempAbbrMap.put("CLST", new String[] { "Antarctica/Palmer", "America/Santiago" }); - tempMap.put("CLT", new String[] { "Antarctica/Palmer", + tempAbbrMap.put("CLT", new String[] { "Antarctica/Palmer", "America/Santiago" }); - tempMap.put("CMT", new String[] { "Europe/Copenhagen", + tempAbbrMap.put("CMT", new String[] { "Europe/Copenhagen", "Europe/Chisinau", "Europe/Tiraspol", "America/St_Lucia", "America/Buenos_Aires", "America/Rosario", "America/Cordoba", "America/Jujuy", "America/Catamarca", "America/Mendoza", "America/Caracas" }); - tempMap.put("COST", new String[] { "America/Bogota" }); - tempMap.put("COT", new String[] { "America/Bogota" }); - tempMap + tempAbbrMap.put("COST", new String[] { "America/Bogota" }); + tempAbbrMap.put("COT", new String[] { "America/Bogota" }); + tempAbbrMap .put("CST", new String[] { "Asia/Harbin", "Asia/Shanghai", "Asia/Chungking", "Asia/Urumqi", "Asia/Kashgar", "Asia/Taipei", "Asia/Macao", "Asia/Jayapura", @@ -389,51 +397,51 @@ "America/Havana", "America/El_Salvador", "America/Guatemala", "America/Tegucigalpa", "America/Managua" }); - tempMap.put("CUT", new String[] { "Europe/Zaporozhye" }); - tempMap.put("CVST", new String[] { "Atlantic/Cape_Verde" }); - tempMap.put("CVT", new String[] { "Atlantic/Cape_Verde" }); - tempMap.put("CWT", new String[] { "America/Chicago", + tempAbbrMap.put("CUT", new String[] { "Europe/Zaporozhye" }); + tempAbbrMap.put("CVST", new String[] { "Atlantic/Cape_Verde" }); + tempAbbrMap.put("CVT", new String[] { "Atlantic/Cape_Verde" }); + tempAbbrMap.put("CWT", new String[] { "America/Chicago", "America/Indianapolis", "America/Indiana/Marengo", "America/Indiana/Knox", "America/Indiana/Vevay", "America/Louisville", "America/Menominee" }); - tempMap.put("CXT", new String[] { "Indian/Christmas" }); - tempMap.put("DACT", new String[] { "Asia/Dacca" }); - tempMap.put("DAVT", new String[] { "Antarctica/Davis" }); - tempMap.put("DDUT", new String[] { "Antarctica/DumontDUrville" }); - tempMap.put("DFT", new String[] { "Europe/Oslo", "Europe/Paris" }); - tempMap.put("DMT", new String[] { "Europe/Belfast", "Europe/Dublin" }); - tempMap.put("DUSST", new String[] { "Asia/Dushanbe" }); - tempMap.put("DUST", new String[] { "Asia/Dushanbe" }); - tempMap.put("EASST", new String[] { "Pacific/Easter" }); - tempMap.put("EAST", new String[] { "Indian/Antananarivo", + tempAbbrMap.put("CXT", new String[] { "Indian/Christmas" }); + tempAbbrMap.put("DACT", new String[] { "Asia/Dacca" }); + tempAbbrMap.put("DAVT", new String[] { "Antarctica/Davis" }); + tempAbbrMap.put("DDUT", new String[] { "Antarctica/DumontDUrville" }); + tempAbbrMap.put("DFT", new String[] { "Europe/Oslo", "Europe/Paris" }); + tempAbbrMap.put("DMT", new String[] { "Europe/Belfast", "Europe/Dublin" }); + tempAbbrMap.put("DUSST", new String[] { "Asia/Dushanbe" }); + tempAbbrMap.put("DUST", new String[] { "Asia/Dushanbe" }); + tempAbbrMap.put("EASST", new String[] { "Pacific/Easter" }); + tempAbbrMap.put("EAST", new String[] { "Indian/Antananarivo", "Pacific/Easter" }); - tempMap.put("EAT", new String[] { "Indian/Comoro", + tempAbbrMap.put("EAT", new String[] { "Indian/Comoro", "Indian/Antananarivo", "Indian/Mayotte", "Africa/Djibouti", "Africa/Asmera", "Africa/Addis_Ababa", "Africa/Nairobi", "Africa/Mogadishu", "Africa/Khartoum", "Africa/Dar_es_Salaam", "Africa/Kampala" }); - tempMap.put("ECT", new String[] { "Pacific/Galapagos", + tempAbbrMap.put("ECT", new String[] { "Pacific/Galapagos", "America/Guayaquil" }); - tempMap.put("EDDT", new String[] { "America/Iqaluit" }); - tempMap.put("EDT", new String[] { "America/New_York", + tempAbbrMap.put("EDDT", new String[] { "America/Iqaluit" }); + tempAbbrMap.put("EDT", new String[] { "America/New_York", "America/Indianapolis", "America/Indiana/Marengo", "America/Indiana/Vevay", "America/Louisville", "America/Detroit", "America/Montreal", "America/Thunder_Bay", "America/Nipigon", "America/Pangnirtung", "America/Iqaluit", "America/Cancun", "America/Nassau", "America/Santo_Domingo", "America/Port-au-Prince", "America/Jamaica", "America/Grand_Turk" }); - tempMap.put("EEMT", new String[] { "Europe/Minsk", "Europe/Chisinau", + tempAbbrMap.put("EEMT", new String[] { "Europe/Minsk", "Europe/Chisinau", "Europe/Tiraspol", "Europe/Kaliningrad", "Europe/Moscow" }); - tempMap.put("EEST", new String[] { "Europe/Minsk", "Europe/Sofia", + tempAbbrMap.put("EEST", new String[] { "Europe/Minsk", "Europe/Sofia", "Europe/Tallinn", "Europe/Helsinki", "Europe/Athens", "Europe/Riga", "Europe/Vilnius", "Europe/Chisinau", "Europe/Tiraspol", "Europe/Warsaw", "Europe/Bucharest", "Europe/Kaliningrad", "Europe/Moscow", "Europe/Istanbul", "Europe/Kiev", "Europe/Uzhgorod", "Europe/Zaporozhye", "Asia/Nicosia", "Asia/Amman", "Asia/Beirut", "Asia/Gaza", "Asia/Damascus", "Africa/Cairo" }); - tempMap.put("EET", new String[] { "Europe/Minsk", "Europe/Sofia", + tempAbbrMap.put("EET", new String[] { "Europe/Minsk", "Europe/Sofia", "Europe/Tallinn", "Europe/Helsinki", "Europe/Athens", "Europe/Riga", "Europe/Vilnius", "Europe/Chisinau", "Europe/Tiraspol", "Europe/Warsaw", "Europe/Bucharest", @@ -442,11 +450,11 @@ "Europe/Simferopol", "Asia/Nicosia", "Asia/Amman", "Asia/Beirut", "Asia/Gaza", "Asia/Damascus", "Africa/Cairo", "Africa/Tripoli" }); - tempMap.put("EGST", new String[] { "America/Scoresbysund" }); - tempMap.put("EGT", new String[] { "Atlantic/Jan_Mayen", + tempAbbrMap.put("EGST", new String[] { "America/Scoresbysund" }); + tempAbbrMap.put("EGT", new String[] { "Atlantic/Jan_Mayen", "America/Scoresbysund" }); - tempMap.put("EHDT", new String[] { "America/Santo_Domingo" }); - tempMap.put("EST", new String[] { "Australia/Brisbane", + tempAbbrMap.put("EHDT", new String[] { "America/Santo_Domingo" }); + tempAbbrMap.put("EST", new String[] { "Australia/Brisbane", "Australia/Lindeman", "Australia/Hobart", "Australia/Melbourne", "Australia/Sydney", "Australia/Broken_Hill", "Australia/Lord_Howe", @@ -460,30 +468,30 @@ "America/Santo_Domingo", "America/Port-au-Prince", "America/Jamaica", "America/Managua", "America/Panama", "America/Grand_Turk" }); - tempMap.put("EWT", new String[] { "America/New_York", + tempAbbrMap.put("EWT", new String[] { "America/New_York", "America/Indianapolis", "America/Indiana/Marengo", "America/Indiana/Vevay", "America/Louisville", "America/Detroit", "America/Jamaica" }); - tempMap.put("FFMT", new String[] { "America/Martinique" }); - tempMap.put("FJST", new String[] { "Pacific/Fiji" }); - tempMap.put("FJT", new String[] { "Pacific/Fiji" }); - tempMap.put("FKST", new String[] { "Atlantic/Stanley" }); - tempMap.put("FKT", new String[] { "Atlantic/Stanley" }); - tempMap.put("FMT", + tempAbbrMap.put("FFMT", new String[] { "America/Martinique" }); + tempAbbrMap.put("FJST", new String[] { "Pacific/Fiji" }); + tempAbbrMap.put("FJT", new String[] { "Pacific/Fiji" }); + tempAbbrMap.put("FKST", new String[] { "Atlantic/Stanley" }); + tempAbbrMap.put("FKT", new String[] { "Atlantic/Stanley" }); + tempAbbrMap.put("FMT", new String[] { "Atlantic/Madeira", "Africa/Freetown" }); - tempMap.put("FNST", new String[] { "America/Noronha" }); - tempMap.put("FNT", new String[] { "America/Noronha" }); - tempMap.put("FRUST", new String[] { "Asia/Bishkek" }); - tempMap.put("FRUT", new String[] { "Asia/Bishkek" }); - tempMap.put("GALT", new String[] { "Pacific/Galapagos" }); - tempMap.put("GAMT", new String[] { "Pacific/Gambier" }); - tempMap.put("GBGT", new String[] { "America/Guyana" }); - tempMap.put("GEST", new String[] { "Asia/Tbilisi" }); - tempMap.put("GET", new String[] { "Asia/Tbilisi" }); - tempMap.put("GFT", new String[] { "America/Cayenne" }); - tempMap.put("GHST", new String[] { "Africa/Accra" }); - tempMap.put("GILT", new String[] { "Pacific/Tarawa" }); - tempMap.put("GMT", new String[] { "Atlantic/St_Helena", + tempAbbrMap.put("FNST", new String[] { "America/Noronha" }); + tempAbbrMap.put("FNT", new String[] { "America/Noronha" }); + tempAbbrMap.put("FRUST", new String[] { "Asia/Bishkek" }); + tempAbbrMap.put("FRUT", new String[] { "Asia/Bishkek" }); + tempAbbrMap.put("GALT", new String[] { "Pacific/Galapagos" }); + tempAbbrMap.put("GAMT", new String[] { "Pacific/Gambier" }); + tempAbbrMap.put("GBGT", new String[] { "America/Guyana" }); + tempAbbrMap.put("GEST", new String[] { "Asia/Tbilisi" }); + tempAbbrMap.put("GET", new String[] { "Asia/Tbilisi" }); + tempAbbrMap.put("GFT", new String[] { "America/Cayenne" }); + tempAbbrMap.put("GHST", new String[] { "Africa/Accra" }); + tempAbbrMap.put("GILT", new String[] { "Pacific/Tarawa" }); + tempAbbrMap.put("GMT", new String[] { "Atlantic/St_Helena", "Atlantic/Reykjavik", "Europe/London", "Europe/Belfast", "Europe/Dublin", "Europe/Gibraltar", "Africa/Porto-Novo", "Africa/Ouagadougou", "Africa/Abidjan", "Africa/Malabo", @@ -492,90 +500,90 @@ "Africa/Timbuktu", "Africa/Nouakchott", "Africa/Niamey", "Africa/Sao_Tome", "Africa/Dakar", "Africa/Freetown", "Africa/Lome" }); - tempMap.put("GST", new String[] { "Atlantic/South_Georgia", + tempAbbrMap.put("GST", new String[] { "Atlantic/South_Georgia", "Asia/Bahrain", "Asia/Muscat", "Asia/Qatar", "Asia/Dubai", "Pacific/Guam" }); - tempMap.put("GYT", new String[] { "America/Guyana" }); - tempMap.put("HADT", new String[] { "America/Adak" }); - tempMap.put("HART", new String[] { "Asia/Harbin" }); - tempMap.put("HAST", new String[] { "America/Adak" }); - tempMap.put("HAWT", new String[] { "America/Adak" }); - tempMap.put("HDT", new String[] { "Pacific/Honolulu" }); - tempMap.put("HKST", new String[] { "Asia/Hong_Kong" }); - tempMap.put("HKT", new String[] { "Asia/Hong_Kong" }); - tempMap.put("HMT", new String[] { "Atlantic/Azores", "Europe/Helsinki", + tempAbbrMap.put("GYT", new String[] { "America/Guyana" }); + tempAbbrMap.put("HADT", new String[] { "America/Adak" }); + tempAbbrMap.put("HART", new String[] { "Asia/Harbin" }); + tempAbbrMap.put("HAST", new String[] { "America/Adak" }); + tempAbbrMap.put("HAWT", new String[] { "America/Adak" }); + tempAbbrMap.put("HDT", new String[] { "Pacific/Honolulu" }); + tempAbbrMap.put("HKST", new String[] { "Asia/Hong_Kong" }); + tempAbbrMap.put("HKT", new String[] { "Asia/Hong_Kong" }); + tempAbbrMap.put("HMT", new String[] { "Atlantic/Azores", "Europe/Helsinki", "Asia/Dacca", "Asia/Calcutta", "America/Havana" }); - tempMap.put("HOVST", new String[] { "Asia/Hovd" }); - tempMap.put("HOVT", new String[] { "Asia/Hovd" }); - tempMap.put("HST", new String[] { "Pacific/Johnston", + tempAbbrMap.put("HOVST", new String[] { "Asia/Hovd" }); + tempAbbrMap.put("HOVT", new String[] { "Asia/Hovd" }); + tempAbbrMap.put("HST", new String[] { "Pacific/Johnston", "Pacific/Honolulu" }); - tempMap.put("HWT", new String[] { "Pacific/Honolulu" }); - tempMap.put("ICT", new String[] { "Asia/Phnom_Penh", "Asia/Vientiane", + tempAbbrMap.put("HWT", new String[] { "Pacific/Honolulu" }); + tempAbbrMap.put("ICT", new String[] { "Asia/Phnom_Penh", "Asia/Vientiane", "Asia/Bangkok", "Asia/Saigon" }); - tempMap.put("IDDT", new String[] { "Asia/Jerusalem", "Asia/Gaza" }); - tempMap.put("IDT", new String[] { "Asia/Jerusalem", "Asia/Gaza" }); - tempMap.put("IHST", new String[] { "Asia/Colombo" }); - tempMap.put("IMT", new String[] { "Europe/Sofia", "Europe/Istanbul", + tempAbbrMap.put("IDDT", new String[] { "Asia/Jerusalem", "Asia/Gaza" }); + tempAbbrMap.put("IDT", new String[] { "Asia/Jerusalem", "Asia/Gaza" }); + tempAbbrMap.put("IHST", new String[] { "Asia/Colombo" }); + tempAbbrMap.put("IMT", new String[] { "Europe/Sofia", "Europe/Istanbul", "Asia/Irkutsk" }); - tempMap.put("IOT", new String[] { "Indian/Chagos" }); - tempMap.put("IRKMT", new String[] { "Asia/Irkutsk" }); - tempMap.put("IRKST", new String[] { "Asia/Irkutsk" }); - tempMap.put("IRKT", new String[] { "Asia/Irkutsk" }); - tempMap.put("IRST", new String[] { "Asia/Tehran" }); - tempMap.put("IRT", new String[] { "Asia/Tehran" }); - tempMap.put("ISST", new String[] { "Atlantic/Reykjavik" }); - tempMap.put("IST", new String[] { "Atlantic/Reykjavik", + tempAbbrMap.put("IOT", new String[] { "Indian/Chagos" }); + tempAbbrMap.put("IRKMT", new String[] { "Asia/Irkutsk" }); + tempAbbrMap.put("IRKST", new String[] { "Asia/Irkutsk" }); + tempAbbrMap.put("IRKT", new String[] { "Asia/Irkutsk" }); + tempAbbrMap.put("IRST", new String[] { "Asia/Tehran" }); + tempAbbrMap.put("IRT", new String[] { "Asia/Tehran" }); + tempAbbrMap.put("ISST", new String[] { "Atlantic/Reykjavik" }); + tempAbbrMap.put("IST", new String[] { "Atlantic/Reykjavik", "Europe/Belfast", "Europe/Dublin", "Asia/Dacca", "Asia/Thimbu", "Asia/Calcutta", "Asia/Jerusalem", "Asia/Katmandu", "Asia/Karachi", "Asia/Gaza", "Asia/Colombo" }); - tempMap.put("JAYT", new String[] { "Asia/Jayapura" }); - tempMap.put("JMT", new String[] { "Atlantic/St_Helena", + tempAbbrMap.put("JAYT", new String[] { "Asia/Jayapura" }); + tempAbbrMap.put("JMT", new String[] { "Atlantic/St_Helena", "Asia/Jerusalem" }); - tempMap.put("JST", new String[] { "Asia/Rangoon", "Asia/Dili", + tempAbbrMap.put("JST", new String[] { "Asia/Rangoon", "Asia/Dili", "Asia/Ujung_Pandang", "Asia/Tokyo", "Asia/Kuala_Lumpur", "Asia/Kuching", "Asia/Manila", "Asia/Singapore", "Pacific/Nauru" }); - tempMap.put("KART", new String[] { "Asia/Karachi" }); - tempMap.put("KAST", new String[] { "Asia/Kashgar" }); - tempMap.put("KDT", new String[] { "Asia/Seoul" }); - tempMap.put("KGST", new String[] { "Asia/Bishkek" }); - tempMap.put("KGT", new String[] { "Asia/Bishkek" }); - tempMap.put("KMT", new String[] { "Europe/Vilnius", "Europe/Kiev", + tempAbbrMap.put("KART", new String[] { "Asia/Karachi" }); + tempAbbrMap.put("KAST", new String[] { "Asia/Kashgar" }); + tempAbbrMap.put("KDT", new String[] { "Asia/Seoul" }); + tempAbbrMap.put("KGST", new String[] { "Asia/Bishkek" }); + tempAbbrMap.put("KGT", new String[] { "Asia/Bishkek" }); + tempAbbrMap.put("KMT", new String[] { "Europe/Vilnius", "Europe/Kiev", "America/Cayman", "America/Jamaica", "America/St_Vincent", "America/Grand_Turk" }); - tempMap.put("KOST", new String[] { "Pacific/Kosrae" }); - tempMap.put("KRAMT", new String[] { "Asia/Krasnoyarsk" }); - tempMap.put("KRAST", new String[] { "Asia/Krasnoyarsk" }); - tempMap.put("KRAT", new String[] { "Asia/Krasnoyarsk" }); - tempMap.put("KST", new String[] { "Asia/Seoul", "Asia/Pyongyang" }); - tempMap.put("KUYMT", new String[] { "Europe/Samara" }); - tempMap.put("KUYST", new String[] { "Europe/Samara" }); - tempMap.put("KUYT", new String[] { "Europe/Samara" }); - tempMap.put("KWAT", new String[] { "Pacific/Kwajalein" }); - tempMap.put("LHST", new String[] { "Australia/Lord_Howe" }); - tempMap.put("LINT", new String[] { "Pacific/Kiritimati" }); - tempMap.put("LKT", new String[] { "Asia/Colombo" }); - tempMap.put("LPMT", new String[] { "America/La_Paz" }); - tempMap.put("LRT", new String[] { "Africa/Monrovia" }); - tempMap.put("LST", new String[] { "Europe/Riga" }); - tempMap.put("M", new String[] { "Europe/Moscow" }); - tempMap.put("MADST", new String[] { "Atlantic/Madeira" }); - tempMap.put("MAGMT", new String[] { "Asia/Magadan" }); - tempMap.put("MAGST", new String[] { "Asia/Magadan" }); - tempMap.put("MAGT", new String[] { "Asia/Magadan" }); - tempMap.put("MALT", new String[] { "Asia/Kuala_Lumpur", + tempAbbrMap.put("KOST", new String[] { "Pacific/Kosrae" }); + tempAbbrMap.put("KRAMT", new String[] { "Asia/Krasnoyarsk" }); + tempAbbrMap.put("KRAST", new String[] { "Asia/Krasnoyarsk" }); + tempAbbrMap.put("KRAT", new String[] { "Asia/Krasnoyarsk" }); + tempAbbrMap.put("KST", new String[] { "Asia/Seoul", "Asia/Pyongyang" }); + tempAbbrMap.put("KUYMT", new String[] { "Europe/Samara" }); + tempAbbrMap.put("KUYST", new String[] { "Europe/Samara" }); + tempAbbrMap.put("KUYT", new String[] { "Europe/Samara" }); + tempAbbrMap.put("KWAT", new String[] { "Pacific/Kwajalein" }); + tempAbbrMap.put("LHST", new String[] { "Australia/Lord_Howe" }); + tempAbbrMap.put("LINT", new String[] { "Pacific/Kiritimati" }); + tempAbbrMap.put("LKT", new String[] { "Asia/Colombo" }); + tempAbbrMap.put("LPMT", new String[] { "America/La_Paz" }); + tempAbbrMap.put("LRT", new String[] { "Africa/Monrovia" }); + tempAbbrMap.put("LST", new String[] { "Europe/Riga" }); + tempAbbrMap.put("M", new String[] { "Europe/Moscow" }); + tempAbbrMap.put("MADST", new String[] { "Atlantic/Madeira" }); + tempAbbrMap.put("MAGMT", new String[] { "Asia/Magadan" }); + tempAbbrMap.put("MAGST", new String[] { "Asia/Magadan" }); + tempAbbrMap.put("MAGT", new String[] { "Asia/Magadan" }); + tempAbbrMap.put("MALT", new String[] { "Asia/Kuala_Lumpur", "Asia/Singapore" }); - tempMap.put("MART", new String[] { "Pacific/Marquesas" }); - tempMap.put("MAWT", new String[] { "Antarctica/Mawson" }); - tempMap.put("MDDT", new String[] { "America/Cambridge_Bay", + tempAbbrMap.put("MART", new String[] { "Pacific/Marquesas" }); + tempAbbrMap.put("MAWT", new String[] { "Antarctica/Mawson" }); + tempAbbrMap.put("MDDT", new String[] { "America/Cambridge_Bay", "America/Yellowknife", "America/Inuvik" }); - tempMap.put("MDST", new String[] { "Europe/Moscow" }); - tempMap.put("MDT", new String[] { "America/Denver", "America/Phoenix", + tempAbbrMap.put("MDST", new String[] { "Europe/Moscow" }); + tempAbbrMap.put("MDT", new String[] { "America/Denver", "America/Phoenix", "America/Boise", "America/Regina", "America/Swift_Current", "America/Edmonton", "America/Cambridge_Bay", "America/Yellowknife", "America/Inuvik", "America/Chihuahua", "America/Hermosillo", "America/Mazatlan" }); - tempMap.put("MET", new String[] { "Europe/Tirane", "Europe/Andorra", + tempAbbrMap.put("MEST", new String[] { "Europe/Tirane", "Europe/Andorra", "Europe/Vienna", "Europe/Minsk", "Europe/Brussels", "Europe/Sofia", "Europe/Prague", "Europe/Copenhagen", "Europe/Tallinn", "Europe/Berlin", "Europe/Gibraltar", @@ -587,212 +595,226 @@ "Europe/Kaliningrad", "Europe/Madrid", "Europe/Stockholm", "Europe/Zurich", "Europe/Kiev", "Europe/Uzhgorod", "Europe/Zaporozhye", "Europe/Simferopol", "Europe/Belgrade", + "Africa/Algiers", "Africa/Tripoli", "Africa/Tunis", + "Africa/Ceuta" }); + tempAbbrMap.put("MET", new String[] { "Europe/Tirane", "Europe/Andorra", + "Europe/Vienna", "Europe/Minsk", "Europe/Brussels", + "Europe/Sofia", "Europe/Prague", "Europe/Copenhagen", + "Europe/Tallinn", "Europe/Berlin", "Europe/Gibraltar", + "Europe/Athens", "Europe/Budapest", "Europe/Rome", + "Europe/Riga", "Europe/Vaduz", "Europe/Vilnius", + "Europe/Luxembourg", "Europe/Malta", "Europe/Chisinau", + "Europe/Tiraspol", "Europe/Monaco", "Europe/Amsterdam", + "Europe/Oslo", "Europe/Warsaw", "Europe/Lisbon", + "Europe/Kaliningrad", "Europe/Madrid", "Europe/Stockholm", + "Europe/Zurich", "Europe/Kiev", "Europe/Uzhgorod", + "Europe/Zaporozhye", "Europe/Simferopol", "Europe/Belgrade", "Africa/Algiers", "Africa/Tripoli", "Africa/Casablanca", "Africa/Tunis", "Africa/Ceuta" }); - tempMap.put("MHT", + tempAbbrMap.put("MHT", new String[] { "Pacific/Majuro", "Pacific/Kwajalein" }); - tempMap.put("MMT", new String[] { "Indian/Maldives", "Europe/Minsk", + tempAbbrMap.put("MMT", new String[] { "Indian/Maldives", "Europe/Minsk", "Europe/Moscow", "Asia/Rangoon", "Asia/Ujung_Pandang", "Asia/Colombo", "Pacific/Easter", "Africa/Monrovia", "America/Managua", "America/Montevideo" }); - tempMap.put("MOST", new String[] { "Asia/Macao" }); - tempMap.put("MOT", new String[] { "Asia/Macao" }); - tempMap.put("MPT", new String[] { "Pacific/Saipan" }); - tempMap.put("MSK", new String[] { "Europe/Minsk", "Europe/Tallinn", + tempAbbrMap.put("MOST", new String[] { "Asia/Macao" }); + tempAbbrMap.put("MOT", new String[] { "Asia/Macao" }); + tempAbbrMap.put("MPT", new String[] { "Pacific/Saipan" }); + tempAbbrMap.put("MSK", new String[] { "Europe/Minsk", "Europe/Tallinn", "Europe/Riga", "Europe/Vilnius", "Europe/Chisinau", "Europe/Kiev", "Europe/Uzhgorod", "Europe/Zaporozhye", "Europe/Simferopol" }); - tempMap.put("MST", new String[] { "Europe/Moscow", "America/Denver", + tempAbbrMap.put("MST", new String[] { "Europe/Moscow", "America/Denver", "America/Phoenix", "America/Boise", "America/Regina", "America/Swift_Current", "America/Edmonton", "America/Dawson_Creek", "America/Cambridge_Bay", "America/Yellowknife", "America/Inuvik", "America/Mexico_City", "America/Chihuahua", "America/Hermosillo", "America/Mazatlan", "America/Tijuana" }); - tempMap.put("MUT", new String[] { "Indian/Mauritius" }); - tempMap.put("MVT", new String[] { "Indian/Maldives" }); - tempMap.put("MWT", new String[] { "America/Denver", "America/Phoenix", + tempAbbrMap.put("MUT", new String[] { "Indian/Mauritius" }); + tempAbbrMap.put("MVT", new String[] { "Indian/Maldives" }); + tempAbbrMap.put("MWT", new String[] { "America/Denver", "America/Phoenix", "America/Boise" }); - tempMap + tempAbbrMap .put("MYT", new String[] { "Asia/Kuala_Lumpur", "Asia/Kuching" }); - tempMap.put("NCST", new String[] { "Pacific/Noumea" }); - tempMap.put("NCT", new String[] { "Pacific/Noumea" }); - tempMap.put("NDT", new String[] { "America/Nome", "America/Adak", + tempAbbrMap.put("NCST", new String[] { "Pacific/Noumea" }); + tempAbbrMap.put("NCT", new String[] { "Pacific/Noumea" }); + tempAbbrMap.put("NDT", new String[] { "America/Nome", "America/Adak", "America/St_Johns", "America/Goose_Bay" }); - tempMap.put("NEGT", new String[] { "America/Paramaribo" }); - tempMap.put("NFT", new String[] { "Europe/Paris", "Europe/Oslo", + tempAbbrMap.put("NEGT", new String[] { "America/Paramaribo" }); + tempAbbrMap.put("NFT", new String[] { "Europe/Paris", "Europe/Oslo", "Pacific/Norfolk" }); - tempMap.put("NMT", new String[] { "Pacific/Norfolk" }); - tempMap.put("NOVMT", new String[] { "Asia/Novosibirsk" }); - tempMap.put("NOVST", new String[] { "Asia/Novosibirsk" }); - tempMap.put("NOVT", new String[] { "Asia/Novosibirsk" }); - tempMap.put("NPT", new String[] { "Asia/Katmandu" }); - tempMap.put("NRT", new String[] { "Pacific/Nauru" }); - tempMap.put("NST", new String[] { "Europe/Amsterdam", + tempAbbrMap.put("NMT", new String[] { "Pacific/Norfolk" }); + tempAbbrMap.put("NOVMT", new String[] { "Asia/Novosibirsk" }); + tempAbbrMap.put("NOVST", new String[] { "Asia/Novosibirsk" }); + tempAbbrMap.put("NOVT", new String[] { "Asia/Novosibirsk" }); + tempAbbrMap.put("NPT", new String[] { "Asia/Katmandu" }); + tempAbbrMap.put("NRT", new String[] { "Pacific/Nauru" }); + tempAbbrMap.put("NST", new String[] { "Europe/Amsterdam", "Pacific/Pago_Pago", "Pacific/Midway", "America/Nome", "America/Adak", "America/St_Johns", "America/Goose_Bay" }); - tempMap.put("NUT", new String[] { "Pacific/Niue" }); - tempMap.put("NWT", new String[] { "America/Nome", "America/Adak" }); - tempMap.put("NZDT", new String[] { "Antarctica/McMurdo" }); - tempMap.put("NZHDT", new String[] { "Pacific/Auckland" }); - tempMap.put("NZST", new String[] { "Antarctica/McMurdo", + tempAbbrMap.put("NUT", new String[] { "Pacific/Niue" }); + tempAbbrMap.put("NWT", new String[] { "America/Nome", "America/Adak" }); + tempAbbrMap.put("NZDT", new String[] { "Antarctica/McMurdo" }); + tempAbbrMap.put("NZHDT", new String[] { "Pacific/Auckland" }); + tempAbbrMap.put("NZST", new String[] { "Antarctica/McMurdo", "Pacific/Auckland" }); - tempMap.put("OMSMT", new String[] { "Asia/Omsk" }); - tempMap.put("OMSST", new String[] { "Asia/Omsk" }); - tempMap.put("OMST", new String[] { "Asia/Omsk" }); - tempMap.put("PDDT", new String[] { "America/Inuvik", + tempAbbrMap.put("OMSMT", new String[] { "Asia/Omsk" }); + tempAbbrMap.put("OMSST", new String[] { "Asia/Omsk" }); + tempAbbrMap.put("OMST", new String[] { "Asia/Omsk" }); + tempAbbrMap.put("PDDT", new String[] { "America/Inuvik", "America/Whitehorse", "America/Dawson" }); - tempMap.put("PDT", new String[] { "America/Los_Angeles", + tempAbbrMap.put("PDT", new String[] { "America/Los_Angeles", "America/Juneau", "America/Boise", "America/Vancouver", "America/Dawson_Creek", "America/Inuvik", "America/Whitehorse", "America/Dawson", "America/Tijuana" }); - tempMap.put("PEST", new String[] { "America/Lima" }); - tempMap.put("PET", new String[] { "America/Lima" }); - tempMap.put("PETMT", new String[] { "Asia/Kamchatka" }); - tempMap.put("PETST", new String[] { "Asia/Kamchatka" }); - tempMap.put("PETT", new String[] { "Asia/Kamchatka" }); - tempMap.put("PGT", new String[] { "Pacific/Port_Moresby" }); - tempMap.put("PHOT", new String[] { "Pacific/Enderbury" }); - tempMap.put("PHST", new String[] { "Asia/Manila" }); - tempMap.put("PHT", new String[] { "Asia/Manila" }); - tempMap.put("PKT", new String[] { "Asia/Karachi" }); - tempMap.put("PMDT", new String[] { "America/Miquelon" }); - tempMap.put("PMMT", new String[] { "Pacific/Port_Moresby" }); - tempMap.put("PMST", new String[] { "America/Miquelon" }); - tempMap.put("PMT", new String[] { "Antarctica/DumontDUrville", + tempAbbrMap.put("PEST", new String[] { "America/Lima" }); + tempAbbrMap.put("PET", new String[] { "America/Lima" }); + tempAbbrMap.put("PETMT", new String[] { "Asia/Kamchatka" }); + tempAbbrMap.put("PETST", new String[] { "Asia/Kamchatka" }); + tempAbbrMap.put("PETT", new String[] { "Asia/Kamchatka" }); + tempAbbrMap.put("PGT", new String[] { "Pacific/Port_Moresby" }); + tempAbbrMap.put("PHOT", new String[] { "Pacific/Enderbury" }); + tempAbbrMap.put("PHST", new String[] { "Asia/Manila" }); + tempAbbrMap.put("PHT", new String[] { "Asia/Manila" }); + tempAbbrMap.put("PKT", new String[] { "Asia/Karachi" }); + tempAbbrMap.put("PMDT", new String[] { "America/Miquelon" }); + tempAbbrMap.put("PMMT", new String[] { "Pacific/Port_Moresby" }); + tempAbbrMap.put("PMST", new String[] { "America/Miquelon" }); + tempAbbrMap.put("PMT", new String[] { "Antarctica/DumontDUrville", "Europe/Prague", "Europe/Paris", "Europe/Monaco", "Africa/Algiers", "Africa/Tunis", "America/Panama", "America/Paramaribo" }); - tempMap.put("PNT", new String[] { "Pacific/Pitcairn" }); - tempMap.put("PONT", new String[] { "Pacific/Ponape" }); - tempMap.put("PPMT", new String[] { "America/Port-au-Prince" }); - tempMap.put("PST", new String[] { "Pacific/Pitcairn", + tempAbbrMap.put("PNT", new String[] { "Pacific/Pitcairn" }); + tempAbbrMap.put("PONT", new String[] { "Pacific/Ponape" }); + tempAbbrMap.put("PPMT", new String[] { "America/Port-au-Prince" }); + tempAbbrMap.put("PST", new String[] { "Pacific/Pitcairn", "America/Los_Angeles", "America/Juneau", "America/Boise", "America/Vancouver", "America/Dawson_Creek", "America/Inuvik", "America/Whitehorse", "America/Dawson", "America/Hermosillo", "America/Mazatlan", "America/Tijuana" }); - tempMap.put("PWT", new String[] { "Pacific/Palau", + tempAbbrMap.put("PWT", new String[] { "Pacific/Palau", "America/Los_Angeles", "America/Juneau", "America/Boise", "America/Tijuana" }); - tempMap.put("PYST", new String[] { "America/Asuncion" }); - tempMap.put("PYT", new String[] { "America/Asuncion" }); - tempMap.put("QMT", new String[] { "America/Guayaquil" }); - tempMap.put("RET", new String[] { "Indian/Reunion" }); - tempMap.put("RMT", new String[] { "Atlantic/Reykjavik", "Europe/Rome", + tempAbbrMap.put("PYST", new String[] { "America/Asuncion" }); + tempAbbrMap.put("PYT", new String[] { "America/Asuncion" }); + tempAbbrMap.put("QMT", new String[] { "America/Guayaquil" }); + tempAbbrMap.put("RET", new String[] { "Indian/Reunion" }); + tempAbbrMap.put("RMT", new String[] { "Atlantic/Reykjavik", "Europe/Rome", "Europe/Riga", "Asia/Rangoon" }); - tempMap.put("S", new String[] { "Europe/Moscow" }); - tempMap.put("SAMMT", new String[] { "Europe/Samara" }); - tempMap + tempAbbrMap.put("S", new String[] { "Europe/Moscow" }); + tempAbbrMap.put("SAMMT", new String[] { "Europe/Samara" }); + tempAbbrMap .put("SAMST", new String[] { "Europe/Samara", "Asia/Samarkand" }); - tempMap.put("SAMT", new String[] { "Europe/Samara", "Asia/Samarkand", + tempAbbrMap.put("SAMT", new String[] { "Europe/Samara", "Asia/Samarkand", "Pacific/Pago_Pago", "Pacific/Apia" }); - tempMap.put("SAST", new String[] { "Africa/Maseru", "Africa/Windhoek", + tempAbbrMap.put("SAST", new String[] { "Africa/Maseru", "Africa/Windhoek", "Africa/Johannesburg", "Africa/Mbabane" }); - tempMap.put("SBT", new String[] { "Pacific/Guadalcanal" }); - tempMap.put("SCT", new String[] { "Indian/Mahe" }); - tempMap.put("SDMT", new String[] { "America/Santo_Domingo" }); - tempMap.put("SGT", new String[] { "Asia/Singapore" }); - tempMap.put("SHEST", new String[] { "Asia/Aqtau" }); - tempMap.put("SHET", new String[] { "Asia/Aqtau" }); - tempMap.put("SJMT", new String[] { "America/Costa_Rica" }); - tempMap.put("SLST", new String[] { "Africa/Freetown" }); - tempMap.put("SMT", new String[] { "Atlantic/Stanley", + tempAbbrMap.put("SBT", new String[] { "Pacific/Guadalcanal" }); + tempAbbrMap.put("SCT", new String[] { "Indian/Mahe" }); + tempAbbrMap.put("SDMT", new String[] { "America/Santo_Domingo" }); + tempAbbrMap.put("SGT", new String[] { "Asia/Singapore" }); + tempAbbrMap.put("SHEST", new String[] { "Asia/Aqtau" }); + tempAbbrMap.put("SHET", new String[] { "Asia/Aqtau" }); + tempAbbrMap.put("SJMT", new String[] { "America/Costa_Rica" }); + tempAbbrMap.put("SLST", new String[] { "Africa/Freetown" }); + tempAbbrMap.put("SMT", new String[] { "Atlantic/Stanley", "Europe/Stockholm", "Europe/Simferopol", "Asia/Phnom_Penh", "Asia/Vientiane", "Asia/Kuala_Lumpur", "Asia/Singapore", "Asia/Saigon", "America/Santiago" }); - tempMap.put("SRT", new String[] { "America/Paramaribo" }); - tempMap.put("SST", + tempAbbrMap.put("SRT", new String[] { "America/Paramaribo" }); + tempAbbrMap.put("SST", new String[] { "Pacific/Pago_Pago", "Pacific/Midway" }); - tempMap.put("SVEMT", new String[] { "Asia/Yekaterinburg" }); - tempMap.put("SVEST", new String[] { "Asia/Yekaterinburg" }); - tempMap.put("SVET", new String[] { "Asia/Yekaterinburg" }); - tempMap.put("SWAT", new String[] { "Africa/Windhoek" }); - tempMap.put("SYOT", new String[] { "Antarctica/Syowa" }); - tempMap.put("TAHT", new String[] { "Pacific/Tahiti" }); - tempMap + tempAbbrMap.put("SVEMT", new String[] { "Asia/Yekaterinburg" }); + tempAbbrMap.put("SVEST", new String[] { "Asia/Yekaterinburg" }); + tempAbbrMap.put("SVET", new String[] { "Asia/Yekaterinburg" }); + tempAbbrMap.put("SWAT", new String[] { "Africa/Windhoek" }); + tempAbbrMap.put("SYOT", new String[] { "Antarctica/Syowa" }); + tempAbbrMap.put("TAHT", new String[] { "Pacific/Tahiti" }); + tempAbbrMap .put("TASST", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); - tempMap.put("TAST", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); - tempMap.put("TBIST", new String[] { "Asia/Tbilisi" }); - tempMap.put("TBIT", new String[] { "Asia/Tbilisi" }); - tempMap.put("TBMT", new String[] { "Asia/Tbilisi" }); - tempMap.put("TFT", new String[] { "Indian/Kerguelen" }); - tempMap.put("TJT", new String[] { "Asia/Dushanbe" }); - tempMap.put("TKT", new String[] { "Pacific/Fakaofo" }); - tempMap.put("TMST", new String[] { "Asia/Ashkhabad" }); - tempMap.put("TMT", new String[] { "Europe/Tallinn", "Asia/Tehran", + tempAbbrMap.put("TAST", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); + tempAbbrMap.put("TBIST", new String[] { "Asia/Tbilisi" }); + tempAbbrMap.put("TBIT", new String[] { "Asia/Tbilisi" }); + tempAbbrMap.put("TBMT", new String[] { "Asia/Tbilisi" }); + tempAbbrMap.put("TFT", new String[] { "Indian/Kerguelen" }); + tempAbbrMap.put("TJT", new String[] { "Asia/Dushanbe" }); + tempAbbrMap.put("TKT", new String[] { "Pacific/Fakaofo" }); + tempAbbrMap.put("TMST", new String[] { "Asia/Ashkhabad" }); + tempAbbrMap.put("TMT", new String[] { "Europe/Tallinn", "Asia/Tehran", "Asia/Ashkhabad" }); - tempMap.put("TOST", new String[] { "Pacific/Tongatapu" }); - tempMap.put("TOT", new String[] { "Pacific/Tongatapu" }); - tempMap.put("TPT", new String[] { "Asia/Dili" }); - tempMap.put("TRST", new String[] { "Europe/Istanbul" }); - tempMap.put("TRT", new String[] { "Europe/Istanbul" }); - tempMap.put("TRUT", new String[] { "Pacific/Truk" }); - tempMap.put("TVT", new String[] { "Pacific/Funafuti" }); - tempMap.put("ULAST", new String[] { "Asia/Ulaanbaatar" }); - tempMap.put("ULAT", new String[] { "Asia/Ulaanbaatar" }); - tempMap.put("URUT", new String[] { "Asia/Urumqi" }); - tempMap.put("UYHST", new String[] { "America/Montevideo" }); - tempMap.put("UYT", new String[] { "America/Montevideo" }); - tempMap.put("UZST", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); - tempMap.put("UZT", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); - tempMap.put("VET", new String[] { "America/Caracas" }); - tempMap.put("VLAMT", new String[] { "Asia/Vladivostok" }); - tempMap.put("VLAST", new String[] { "Asia/Vladivostok" }); - tempMap.put("VLAT", new String[] { "Asia/Vladivostok" }); - tempMap.put("VUST", new String[] { "Pacific/Efate" }); - tempMap.put("VUT", new String[] { "Pacific/Efate" }); - tempMap.put("WAKT", new String[] { "Pacific/Wake" }); - tempMap.put("WARST", + tempAbbrMap.put("TOST", new String[] { "Pacific/Tongatapu" }); + tempAbbrMap.put("TOT", new String[] { "Pacific/Tongatapu" }); + tempAbbrMap.put("TPT", new String[] { "Asia/Dili" }); + tempAbbrMap.put("TRST", new String[] { "Europe/Istanbul" }); + tempAbbrMap.put("TRT", new String[] { "Europe/Istanbul" }); + tempAbbrMap.put("TRUT", new String[] { "Pacific/Truk" }); + tempAbbrMap.put("TVT", new String[] { "Pacific/Funafuti" }); + tempAbbrMap.put("ULAST", new String[] { "Asia/Ulaanbaatar" }); + tempAbbrMap.put("ULAT", new String[] { "Asia/Ulaanbaatar" }); + tempAbbrMap.put("URUT", new String[] { "Asia/Urumqi" }); + tempAbbrMap.put("UYHST", new String[] { "America/Montevideo" }); + tempAbbrMap.put("UYT", new String[] { "America/Montevideo" }); + tempAbbrMap.put("UZST", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); + tempAbbrMap.put("UZT", new String[] { "Asia/Samarkand", "Asia/Tashkent" }); + tempAbbrMap.put("VET", new String[] { "America/Caracas" }); + tempAbbrMap.put("VLAMT", new String[] { "Asia/Vladivostok" }); + tempAbbrMap.put("VLAST", new String[] { "Asia/Vladivostok" }); + tempAbbrMap.put("VLAT", new String[] { "Asia/Vladivostok" }); + tempAbbrMap.put("VUST", new String[] { "Pacific/Efate" }); + tempAbbrMap.put("VUT", new String[] { "Pacific/Efate" }); + tempAbbrMap.put("WAKT", new String[] { "Pacific/Wake" }); + tempAbbrMap.put("WARST", new String[] { "America/Jujuy", "America/Mendoza" }); - tempMap + tempAbbrMap .put("WART", new String[] { "America/Jujuy", "America/Mendoza" }); - tempMap.put("WAST", + tempAbbrMap.put("WAST", new String[] { "Africa/Ndjamena", "Africa/Windhoek" }); - tempMap.put("WAT", new String[] { "Africa/Luanda", "Africa/Porto-Novo", + tempAbbrMap.put("WAT", new String[] { "Africa/Luanda", "Africa/Porto-Novo", "Africa/Douala", "Africa/Bangui", "Africa/Ndjamena", "Africa/Kinshasa", "Africa/Brazzaville", "Africa/Malabo", "Africa/Libreville", "Africa/Banjul", "Africa/Conakry", "Africa/Bissau", "Africa/Bamako", "Africa/Nouakchott", "Africa/El_Aaiun", "Africa/Windhoek", "Africa/Niamey", "Africa/Lagos", "Africa/Dakar", "Africa/Freetown" }); - tempMap.put("WEST", new String[] { "Atlantic/Faeroe", + tempAbbrMap.put("WEST", new String[] { "Atlantic/Faeroe", "Atlantic/Azores", "Atlantic/Madeira", "Atlantic/Canary", "Europe/Brussels", "Europe/Luxembourg", "Europe/Monaco", "Europe/Lisbon", "Europe/Madrid", "Africa/Algiers", "Africa/Casablanca", "Africa/Ceuta" }); - tempMap.put("WET", new String[] { "Atlantic/Faeroe", "Atlantic/Azores", + tempAbbrMap.put("WET", new String[] { "Atlantic/Faeroe", "Atlantic/Azores", "Atlantic/Madeira", "Atlantic/Canary", "Europe/Andorra", "Europe/Brussels", "Europe/Luxembourg", "Europe/Monaco", "Europe/Lisbon", "Europe/Madrid", "Africa/Algiers", "Africa/Casablanca", "Africa/El_Aaiun", "Africa/Ceuta" }); - tempMap.put("WFT", new String[] { "Pacific/Wallis" }); - tempMap.put("WGST", new String[] { "America/Godthab" }); - tempMap.put("WGT", new String[] { "America/Godthab" }); - tempMap.put("WMT", new String[] { "Europe/Vilnius", "Europe/Warsaw" }); - tempMap.put("WST", new String[] { "Antarctica/Casey", "Pacific/Apia", + tempAbbrMap.put("WFT", new String[] { "Pacific/Wallis" }); + tempAbbrMap.put("WGST", new String[] { "America/Godthab" }); + tempAbbrMap.put("WGT", new String[] { "America/Godthab" }); + tempAbbrMap.put("WMT", new String[] { "Europe/Vilnius", "Europe/Warsaw" }); + tempAbbrMap.put("WST", new String[] { "Antarctica/Casey", "Pacific/Apia", "Australia/Perth" }); - tempMap.put("YAKMT", new String[] { "Asia/Yakutsk" }); - tempMap.put("YAKST", new String[] { "Asia/Yakutsk" }); - tempMap.put("YAKT", new String[] { "Asia/Yakutsk" }); - tempMap.put("YAPT", new String[] { "Pacific/Yap" }); - tempMap.put("YDDT", new String[] { "America/Whitehorse", + tempAbbrMap.put("YAKMT", new String[] { "Asia/Yakutsk" }); + tempAbbrMap.put("YAKST", new String[] { "Asia/Yakutsk" }); + tempAbbrMap.put("YAKT", new String[] { "Asia/Yakutsk" }); + tempAbbrMap.put("YAPT", new String[] { "Pacific/Yap" }); + tempAbbrMap.put("YDDT", new String[] { "America/Whitehorse", "America/Dawson" }); - tempMap.put("YDT", new String[] { "America/Yakutat", + tempAbbrMap.put("YDT", new String[] { "America/Yakutat", "America/Whitehorse", "America/Dawson" }); - tempMap.put("YEKMT", new String[] { "Asia/Yekaterinburg" }); - tempMap.put("YEKST", new String[] { "Asia/Yekaterinburg" }); - tempMap.put("YEKT", new String[] { "Asia/Yekaterinburg" }); - tempMap.put("YERST", new String[] { "Asia/Yerevan" }); - tempMap.put("YERT", new String[] { "Asia/Yerevan" }); - tempMap.put("YST", new String[] { "America/Yakutat", + tempAbbrMap.put("YEKMT", new String[] { "Asia/Yekaterinburg" }); + tempAbbrMap.put("YEKST", new String[] { "Asia/Yekaterinburg" }); + tempAbbrMap.put("YEKT", new String[] { "Asia/Yekaterinburg" }); + tempAbbrMap.put("YERST", new String[] { "Asia/Yerevan" }); + tempAbbrMap.put("YERT", new String[] { "Asia/Yerevan" }); + tempAbbrMap.put("YST", new String[] { "America/Yakutat", "America/Whitehorse", "America/Dawson" }); - tempMap.put("YWT", new String[] { "America/Yakutat" }); + tempAbbrMap.put("YWT", new String[] { "America/Yakutat" }); - ABBREVIATED_TIMEZONES = Collections.unmodifiableMap(tempMap); + ABBREVIATED_TIMEZONES = Collections.unmodifiableMap(tempAbbrMap); } /** @@ -809,7 +831,7 @@ * * @return the times changed to the timezone 'toTz' */ - public static Time changeTimezone(Connection conn, + public static Time changeTimezone(MySQLConnection conn, Calendar sessionCalendar, Calendar targetCalendar, Time t, @@ -871,7 +893,7 @@ * * @return the timestamp changed to the timezone 'toTz' */ - public static Timestamp changeTimezone(Connection conn, + public static Timestamp changeTimezone(MySQLConnection conn, Calendar sessionCalendar, Calendar targetCalendar, Timestamp tstamp, @@ -975,11 +997,38 @@ } dateCal.clear(); + dateCal.set(Calendar.MILLISECOND, 0); + + // why-oh-why is this different than java.util.date, + // in the year part, but it still keeps the silly '0' + // for the start month???? + dateCal.set(year, month - 1, day, 0, 0, 0); + + long dateAsMillis = 0; + try { + dateAsMillis = dateCal.getTimeInMillis(); + } catch (IllegalAccessError iae) { + // Must be on JDK-1.3.1 or older.... + dateAsMillis = dateCal.getTime().getTime(); + } + + return new Date(dateAsMillis); + } + + final static Date fastDateCreate(int year, int month, int day, Calendar targetCalendar) { + + + Calendar dateCal = (targetCalendar == null) ? new GregorianCalendar() : targetCalendar; + + dateCal.clear(); + + // why-oh-why is this different than java.util.date, // in the year part, but it still keeps the silly '0' // for the start month???? dateCal.set(year, month - 1, day, 0, 0, 0); + dateCal.set(Calendar.MILLISECOND, 0); long dateAsMillis = 0; @@ -994,23 +1043,23 @@ } final static Time fastTimeCreate(Calendar cal, int hour, int minute, - int second) throws SQLException { - if (hour < 0 || hour > 23) { + int second, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (hour < 0 || hour > 24) { throw SQLError.createSQLException("Illegal hour value '" + hour + "' for java.sql.Time type in value '" + timeFormattedString(hour, minute, second) + ".", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } if (minute < 0 || minute > 59) { throw SQLError.createSQLException("Illegal minute value '" + minute + "'" + "' for java.sql.Time type in value '" + timeFormattedString(hour, minute, second) + ".", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } if (second < 0 || second > 59) { throw SQLError.createSQLException("Illegal minute value '" + second + "'" + "' for java.sql.Time type in value '" + timeFormattedString(hour, minute, second) + ".", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } cal.clear(); @@ -1030,6 +1079,44 @@ return new Time(timeAsMillis); } + final static Time fastTimeCreate(int hour, int minute, + int second, Calendar targetCalendar, ExceptionInterceptor exceptionInterceptor) throws SQLException { + if (hour < 0 || hour > 23) { + throw SQLError.createSQLException("Illegal hour value '" + hour + "' for java.sql.Time type in value '" + + timeFormattedString(hour, minute, second) + ".", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + + if (minute < 0 || minute > 59) { + throw SQLError.createSQLException("Illegal minute value '" + minute + "'" + "' for java.sql.Time type in value '" + + timeFormattedString(hour, minute, second) + ".", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + + if (second < 0 || second > 59) { + throw SQLError.createSQLException("Illegal minute value '" + second + "'" + "' for java.sql.Time type in value '" + + timeFormattedString(hour, minute, second) + ".", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + } + + Calendar cal = (targetCalendar == null) ? new GregorianCalendar() : targetCalendar; + cal.clear(); + + // Set 'date' to epoch of Jan 1, 1970 + cal.set(1970, 0, 1, hour, minute, second); + + long timeAsMillis = 0; + + try { + timeAsMillis = cal.getTimeInMillis(); + } catch (IllegalAccessError iae) { + // Must be on JDK-1.3.1 or older.... + timeAsMillis = cal.getTime().getTime(); + } + + return new Time(timeAsMillis); + } + final static Timestamp fastTimestampCreate(boolean useGmtConversion, Calendar gmtCalIfNeeded, Calendar cal, int year, @@ -1060,8 +1147,13 @@ offsetDiff = fromOffset - toOffset; } + if (secondsPart != 0) { + cal.set(Calendar.MILLISECOND, secondsPart / 1000000); + } + long tsAsMillis = 0; + try { tsAsMillis = cal.getTimeInMillis(); } catch (IllegalAccessError iae) { @@ -1070,29 +1162,65 @@ } Timestamp ts = new Timestamp(tsAsMillis + offsetDiff); + ts.setNanos(secondsPart); return ts; } + + final static Timestamp fastTimestampCreate(TimeZone tz, int year, + int month, int day, int hour, int minute, int seconds, + int secondsPart) { + Calendar cal = (tz == null) ? new GregorianCalendar() : new GregorianCalendar(tz); + cal.clear(); + + // why-oh-why is this different than java.util.date, + // in the year part, but it still keeps the silly '0' + // for the start month???? + cal.set(year, month - 1, day, hour, minute, seconds); + long tsAsMillis = 0; + + try { + tsAsMillis = cal.getTimeInMillis(); + } catch (IllegalAccessError iae) { + // Must be on JDK-1.3.1 or older.... + tsAsMillis = cal.getTime().getTime(); + } + + Timestamp ts = new Timestamp(tsAsMillis); + ts.setNanos(secondsPart); + + return ts; + } + /** * Returns the 'official' Java timezone name for the given timezone * * @param timezoneStr * the 'common' timezone name * * @return the Java timezone name for the given timezone + * @throws SQLException * * @throws IllegalArgumentException * DOCUMENT ME! */ - public static String getCanoncialTimezone(String timezoneStr) { + public static String getCanoncialTimezone(String timezoneStr, ExceptionInterceptor exceptionInterceptor) throws SQLException { if (timezoneStr == null) { return null; } timezoneStr = timezoneStr.trim(); + // handle '+/-hh:mm' form ... + + if (timezoneStr.length() > 2) { + if ((timezoneStr.charAt(0) == '+' || timezoneStr.charAt(0) == '-') && + Character.isDigit(timezoneStr.charAt(1))) { + return "GMT" + timezoneStr; + } + } // Fix windows Daylight/Standard shift JDK doesn't map these (doh) int daylightIndex = StringUtils.indexOfIgnoreCase(timezoneStr, @@ -1107,38 +1235,29 @@ timezoneStr = timezoneBuf.toString(); } - String canonicalTz = (String) TIMEZONE_MAPPINGS.get(timezoneStr); + String canonicalTz = TIMEZONE_MAPPINGS.get(timezoneStr); // if we didn't find it, try abbreviated timezones if (canonicalTz == null) { - String[] abbreviatedTimezone = (String[]) ABBREVIATED_TIMEZONES + String[] abbreviatedTimezone = ABBREVIATED_TIMEZONES .get(timezoneStr); if (abbreviatedTimezone != null) { // If there's only one mapping use that if (abbreviatedTimezone.length == 1) { canonicalTz = abbreviatedTimezone[0]; } else { - StringBuffer errorMsg = new StringBuffer( - "The server timezone value '"); - errorMsg.append(timezoneStr); - errorMsg - .append("' represents more than one timezone. You must "); - errorMsg - .append("configure either the server or client to use a "); - errorMsg - .append("more specifc timezone value if you want to enable "); - errorMsg.append("timezone support. The timezones that '"); - errorMsg.append(timezoneStr); - errorMsg.append("' maps to are: "); - errorMsg.append(abbreviatedTimezone[0]); - + StringBuffer possibleTimezones = new StringBuffer(128); + + possibleTimezones.append(abbreviatedTimezone[0]); + for (int i = 1; i < abbreviatedTimezone.length; i++) { - errorMsg.append(", "); - errorMsg.append(abbreviatedTimezone[i]); + possibleTimezones.append(", "); + possibleTimezones.append(abbreviatedTimezone[i]); } - throw new IllegalArgumentException(errorMsg.toString()); + throw SQLError.createSQLException(Messages.getString("TimeUtil.TooGenericTimezoneId", + new Object[] {timezoneStr, possibleTimezones}), SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, exceptionInterceptor); } } } @@ -1153,7 +1272,6 @@ private static String timeFormattedString(int hours, int minutes, int seconds) { StringBuffer buf = new StringBuffer(8); - if (hours < 10) { buf.append("0"); } @@ -1176,4 +1294,39 @@ return buf.toString(); } + + public static String formatNanos(int nanos, boolean serverSupportsFracSecs, boolean usingMicros) { + + // get only last 9 digits + if (nanos > 999999999) { + nanos %= 100000000; + } + + if (usingMicros) { + nanos /= 1000; + } + + if (!serverSupportsFracSecs || nanos == 0) { + return "0"; + } + + final int digitCount = usingMicros ? 6 : 9; + + String nanosString = Integer.toString(nanos); + final String zeroPadding = usingMicros ? "000000" : "000000000"; + + nanosString = zeroPadding.substring(0, (digitCount-nanosString.length())) + + nanosString; + + int pos = digitCount-1; // the end, we're padded to the end by the code above + + while (nanosString.charAt(pos) == '0') { + pos--; + } + + nanosString = nanosString.substring(0, pos + 1); + + return nanosString; + } + } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/UpdatableResultSet.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/UpdatableResultSet.java (.../UpdatableResultSet.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/UpdatableResultSet.java (.../UpdatableResultSet.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,51 +1,49 @@ /* - Copyright (C) 2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; -import com.mysql.jdbc.profiler.ProfileEventSink; -import com.mysql.jdbc.profiler.ProfilerEvent; - import java.math.BigDecimal; - import java.sql.SQLException; - +import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import com.mysql.jdbc.profiler.ProfilerEvent; + /** * A result set that is updatable. - * + * * @author Mark Matthews */ -public class UpdatableResultSet extends ResultSet { +public class UpdatableResultSet extends ResultSetImpl { /** Marker for 'stream' data when doing INSERT rows */ - private final static byte[] STREAM_DATA_MARKER = "** STREAM DATA **" //$NON-NLS-1$ - .getBytes(); + final static byte[] STREAM_DATA_MARKER = StringUtils.getBytes("** STREAM DATA **"); //$NON-NLS-1$ - private SingleByteCharsetConverter charConverter; + protected SingleByteCharsetConverter charConverter; private String charEncoding; @@ -60,7 +58,7 @@ private boolean initializedCharConverter = false; /** PreparedStatement used to insert data */ - private com.mysql.jdbc.PreparedStatement inserter = null; + protected com.mysql.jdbc.PreparedStatement inserter = null; private String insertSQL = null; @@ -71,7 +69,7 @@ private String notUpdatableReason = null; /** List of primary keys */ - private List primaryKeyIndicies = null; + private List primaryKeyIndicies = null; private String qualifiedAndQuotedTableName; @@ -83,42 +81,22 @@ private String refreshSQL = null; /** The binary data for the 'current' row */ - private Object[] savedCurrentRow; + private ResultSetRow savedCurrentRow; - private String tableOnlyName; - /** PreparedStatement used to delete data */ - private com.mysql.jdbc.PreparedStatement updater = null; + protected com.mysql.jdbc.PreparedStatement updater = null; /** SQL for in-place modifcation */ private String updateSQL = null; - + private boolean populateInserterWithDefaultValues = false; - /** - * Create a result set for an executeUpdate statement. - * - * @param updateCount - * the number of rows affected by the update - * @param updateID - * the autoincrement value (if any) - * @param conn - * DOCUMENT ME! - * @param creatorStmt - * DOCUMENT ME! - * - * @throws SQLException - * DOCUMENT ME! - */ - public UpdatableResultSet(long updateCount, long updateID, Connection conn, - Statement creatorStmt) throws SQLException { - super(updateCount, updateID, conn, creatorStmt); - checkUpdatability(); - } + private Map>> databasesUsedToTablesUsed = null; + /** * Creates a new ResultSet object. - * + * * @param catalog * the database in use when we were created * @param fields @@ -129,52 +107,52 @@ * the Connection that created us. * @param creatorStmt * DOCUMENT ME! - * + * * @throws SQLException * DOCUMENT ME! */ - public UpdatableResultSet(String catalog, Field[] fields, RowData tuples, - Connection conn, Statement creatorStmt) throws SQLException { + protected UpdatableResultSet(String catalog, Field[] fields, RowData tuples, + MySQLConnection conn, StatementImpl creatorStmt) throws SQLException { super(catalog, fields, tuples, conn, creatorStmt); checkUpdatability(); - this.populateInserterWithDefaultValues = + this.populateInserterWithDefaultValues = this.connection.getPopulateInsertRowWithDefaultValues(); } /** * JDBC 2.0 - * + * *

    * Move to an absolute row number in the result set. *

    - * + * *

    * If row is positive, moves to an absolute row with respect to the * beginning of the result set. The first row is row 1, the second is row 2, * etc. *

    - * + * *

    * If row is negative, moves to an absolute row position with respect to the * end of result set. For example, calling absolute(-1) positions the cursor * on the last row, absolute(-2) indicates the next-to-last row, etc. *

    - * + * *

    * An attempt to position the cursor beyond the first/last row in the result * set, leaves the cursor before/after the first/last row, respectively. *

    - * + * *

    * Note: Calling absolute(1) is the same as calling first(). Calling * absolute(-1) is the same as calling last(). *

    - * + * * @param row * DOCUMENT ME! - * + * * @return true if on the result set, false if off. - * + * * @exception SQLException * if a database-access error occurs, or row is 0, or result * set type is TYPE_FORWARD_ONLY. @@ -185,12 +163,12 @@ /** * JDBC 2.0 - * + * *

    * Moves to the end of the result set, just after the last row. Has no * effect if the result set contains no rows. *

    - * + * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWARD_ONLY. @@ -201,12 +179,12 @@ /** * JDBC 2.0 - * + * *

    * Moves to the front of the result set, just before the first row. Has no * effect if the result set contains no rows. *

    - * + * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWARD_ONLY @@ -220,7 +198,7 @@ * updateXXX() method(s) and before calling updateRow() to rollback the * updates made to a row. If no updates have been made or updateRow() has * already been called, then this method has no effect. - * + * * @exception SQLException * if a database-access error occurs, or if called when on * the insert row. @@ -236,10 +214,10 @@ /* * (non-Javadoc) - * + * * @see com.mysql.jdbc.ResultSet#checkRowPos() */ - protected void checkRowPos() throws SQLException { + protected synchronized void checkRowPos() throws SQLException { checkClosed(); if (!this.onInsertRow) { @@ -249,210 +227,215 @@ /** * Is this ResultSet updateable? - * + * * @throws SQLException * DOCUMENT ME! */ protected void checkUpdatability() throws SQLException { - if (this.fields == null) { - // we've been created to be populated with cached - // metadata, and we don't have the metadata yet, - // we'll be called again by - // Connection.initializeResultsMetadataFromCache() - // when the metadata has been made available - - return; - } - - String singleTableName = null; - String catalogName = null; - - int primaryKeyCount = 0; - - // We can only do this if we know that there is a currently - // selected database, or if we're talking to a > 4.1 version - // of MySQL server (as it returns database names in field - // info) - // - if ((this.catalog == null) || (this.catalog.length() == 0)) { - this.catalog = this.fields[0].getDatabaseName(); - - if ((this.catalog == null) || (this.catalog.length() == 0)) { - throw SQLError.createSQLException(Messages - .getString("UpdatableResultSet.43") //$NON-NLS-1$ - , SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - if (this.fields.length > 0) { - singleTableName = this.fields[0].getOriginalTableName(); - catalogName = this.fields[0].getDatabaseName(); - - if (singleTableName == null) { - singleTableName = this.fields[0].getTableName(); - catalogName = this.catalog; - } - - if (singleTableName != null && singleTableName.length() == 0) { - this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.3"); - + try { + if (this.fields == null) { + // we've been created to be populated with cached + // metadata, and we don't have the metadata yet, + // we'll be called again by + // Connection.initializeResultsMetadataFromCache() + // when the metadata has been made available + return; } - - if (this.fields[0].isPrimaryKey()) { - primaryKeyCount++; - } - + + String singleTableName = null; + String catalogName = null; + + int primaryKeyCount = 0; + + // We can only do this if we know that there is a currently + // selected database, or if we're talking to a > 4.1 version + // of MySQL server (as it returns database names in field + // info) // - // References only one table? - // - for (int i = 1; i < this.fields.length; i++) { - String otherTableName = this.fields[i].getOriginalTableName(); - String otherCatalogName = this.fields[i].getDatabaseName(); - - if (otherTableName == null) { - otherTableName = this.fields[i].getTableName(); - otherCatalogName = this.catalog; + if ((this.catalog == null) || (this.catalog.length() == 0)) { + this.catalog = this.fields[0].getDatabaseName(); + + if ((this.catalog == null) || (this.catalog.length() == 0)) { + throw SQLError.createSQLException(Messages + .getString("UpdatableResultSet.43") //$NON-NLS-1$ + , SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$ } - - if (otherTableName != null && otherTableName.length() == 0) { + } + + if (this.fields.length > 0) { + singleTableName = this.fields[0].getOriginalTableName(); + catalogName = this.fields[0].getDatabaseName(); + + if (singleTableName == null) { + singleTableName = this.fields[0].getTableName(); + catalogName = this.catalog; + } + + if (singleTableName != null && singleTableName.length() == 0) { this.isUpdatable = false; this.notUpdatableReason = Messages.getString("NotUpdatableReason.3"); - + return; } - - if ((singleTableName == null) - || !otherTableName.equals(singleTableName)) { - this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.0"); - - return; + + if (this.fields[0].isPrimaryKey()) { + primaryKeyCount++; } - - // Can't reference more than one database - if ((catalogName == null) - || !otherCatalogName.equals(catalogName)) { + + // + // References only one table? + // + for (int i = 1; i < this.fields.length; i++) { + String otherTableName = this.fields[i].getOriginalTableName(); + String otherCatalogName = this.fields[i].getDatabaseName(); + + if (otherTableName == null) { + otherTableName = this.fields[i].getTableName(); + otherCatalogName = this.catalog; + } + + if (otherTableName != null && otherTableName.length() == 0) { + this.isUpdatable = false; + this.notUpdatableReason = Messages.getString("NotUpdatableReason.3"); + + return; + } + + if ((singleTableName == null) + || !otherTableName.equals(singleTableName)) { + this.isUpdatable = false; + this.notUpdatableReason = Messages.getString("NotUpdatableReason.0"); + + return; + } + + // Can't reference more than one database + if ((catalogName == null) + || !otherCatalogName.equals(catalogName)) { + this.isUpdatable = false; + this.notUpdatableReason = Messages.getString("NotUpdatableReason.1"); + + return; + } + + if (this.fields[i].isPrimaryKey()) { + primaryKeyCount++; + } + } + + if ((singleTableName == null) || (singleTableName.length() == 0)) { this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.1"); - + this.notUpdatableReason = Messages.getString("NotUpdatableReason.2"); + return; } - - if (this.fields[i].isPrimaryKey()) { - primaryKeyCount++; - } - } - - if ((singleTableName == null) || (singleTableName.length() == 0)) { + } else { this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.2"); - + this.notUpdatableReason = Messages.getString("NotUpdatableReason.3"); + return; } - } else { - this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.3"); - - return; - } - - if (this.connection.getStrictUpdates()) { - java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); - - java.sql.ResultSet rs = null; - HashMap primaryKeyNames = new HashMap(); - - try { - rs = dbmd.getPrimaryKeys(catalogName, null, singleTableName); - - while (rs.next()) { - String keyName = rs.getString(4); - keyName = keyName.toUpperCase(); - primaryKeyNames.put(keyName, keyName); - } - } finally { - if (rs != null) { - try { - rs.close(); - } catch (Exception ex) { - AssertionFailedException.shouldNotHappen(ex); + + if (this.connection.getStrictUpdates()) { + java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); + + java.sql.ResultSet rs = null; + HashMap primaryKeyNames = new HashMap(); + + try { + rs = dbmd.getPrimaryKeys(catalogName, null, singleTableName); + + while (rs.next()) { + String keyName = rs.getString(4); + keyName = keyName.toUpperCase(); + primaryKeyNames.put(keyName, keyName); } - - rs = null; + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception ex) { + AssertionFailedException.shouldNotHappen(ex); + } + + rs = null; + } } - } - - int existingPrimaryKeysCount = primaryKeyNames.size(); - - if (existingPrimaryKeysCount == 0) { - this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.5"); - - return; // we can't update tables w/o keys - } - - // - // Contains all primary keys? - // - for (int i = 0; i < this.fields.length; i++) { - if (this.fields[i].isPrimaryKey()) { - String columnNameUC = this.fields[i].getName() - .toUpperCase(); - - if (primaryKeyNames.remove(columnNameUC) == null) { - // try original name - String originalName = this.fields[i].getOriginalName(); - - if (originalName != null) { - if (primaryKeyNames.remove(originalName - .toUpperCase()) == null) { - // we don't know about this key, so give up :( - this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.6", - new Object[] {originalName}); - - return; + + int existingPrimaryKeysCount = primaryKeyNames.size(); + + if (existingPrimaryKeysCount == 0) { + this.isUpdatable = false; + this.notUpdatableReason = Messages.getString("NotUpdatableReason.5"); + + return; // we can't update tables w/o keys + } + + // + // Contains all primary keys? + // + for (int i = 0; i < this.fields.length; i++) { + if (this.fields[i].isPrimaryKey()) { + String columnNameUC = this.fields[i].getName() + .toUpperCase(); + + if (primaryKeyNames.remove(columnNameUC) == null) { + // try original name + String originalName = this.fields[i].getOriginalName(); + + if (originalName != null) { + if (primaryKeyNames.remove(originalName + .toUpperCase()) == null) { + // we don't know about this key, so give up :( + this.isUpdatable = false; + this.notUpdatableReason = Messages.getString("NotUpdatableReason.6", + new Object[] {originalName}); + + return; + } } } } } - } - - this.isUpdatable = primaryKeyNames.isEmpty(); - - if (!this.isUpdatable) { - if (existingPrimaryKeysCount > 1) { - this.notUpdatableReason = Messages.getString("NotUpdatableReason.7"); - } else { - this.notUpdatableReason = Messages.getString("NotUpdatableReason.4"); + + this.isUpdatable = primaryKeyNames.isEmpty(); + + if (!this.isUpdatable) { + if (existingPrimaryKeysCount > 1) { + this.notUpdatableReason = Messages.getString("NotUpdatableReason.7"); + } else { + this.notUpdatableReason = Messages.getString("NotUpdatableReason.4"); + } + + return; } - + } + + // + // Must have at least one primary key + // + if (primaryKeyCount == 0) { + this.isUpdatable = false; + this.notUpdatableReason = Messages.getString("NotUpdatableReason.4"); + return; } - } - - // - // Must have at least one primary key - // - if (primaryKeyCount == 0) { - this.isUpdatable = false; - this.notUpdatableReason = Messages.getString("NotUpdatableReason.4"); - + + this.isUpdatable = true; + this.notUpdatableReason = null; + return; + } catch (SQLException sqlEx) { + this.isUpdatable = false; + this.notUpdatableReason = sqlEx.getMessage(); } - - this.isUpdatable = true; - this.notUpdatableReason = null; - - return; } /** * JDBC 2.0 Delete the current row from the result set and the underlying * database. Cannot be called when on the insert row. - * + * * @exception SQLException * if a database-access error occurs, or if called when on * the insert row. @@ -467,122 +450,150 @@ } if (this.onInsertRow) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.1")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.1"), getExceptionInterceptor()); //$NON-NLS-1$ } else if (this.rowData.size() == 0) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.2")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.2"), getExceptionInterceptor()); //$NON-NLS-1$ } else if (isBeforeFirst()) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.3")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.3"), getExceptionInterceptor()); //$NON-NLS-1$ } else if (isAfterLast()) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.4")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.4"), getExceptionInterceptor()); //$NON-NLS-1$ } if (this.deleter == null) { if (this.deleteSQL == null) { generateStatements(); } - this.deleter = this.connection + this.deleter = (PreparedStatement) this.connection .clientPrepareStatement(this.deleteSQL); } this.deleter.clearParameters(); - String characterEncoding = null; + int numKeys = this.primaryKeyIndicies.size(); - if (this.connection.getUseUnicode()) { - characterEncoding = this.connection.getEncoding(); - } - - // - // FIXME: Use internal routines where possible for character - // conversion! - try { - int numKeys = this.primaryKeyIndicies.size(); - - if (numKeys == 1) { - int index = ((Integer) this.primaryKeyIndicies.get(0)) + if (numKeys == 1) { + int index = this.primaryKeyIndicies.get(0) + .intValue(); + this.setParamValue(this.deleter, 1, this.thisRow, + index, this.fields[index].getSQLType()); + } else { + for (int i = 0; i < numKeys; i++) { + int index = this.primaryKeyIndicies.get(i) .intValue(); - String currentVal = ((characterEncoding == null) ? new String( - (byte[]) this.thisRow[index]) : new String( - (byte[]) this.thisRow[index], characterEncoding)); - this.deleter.setString(1, currentVal); - } else { - for (int i = 0; i < numKeys; i++) { - int index = ((Integer) this.primaryKeyIndicies.get(i)) - .intValue(); - String currentVal = ((characterEncoding == null) ? new String( - (byte[]) this.thisRow[index]) - : new String((byte[]) this.thisRow[index], - characterEncoding)); - this.deleter.setString(i + 1, currentVal); - } + this.setParamValue(this.deleter, i + 1, this.thisRow, + index, this.fields[index].getSQLType()); + } + } - this.deleter.executeUpdate(); - this.rowData.removeRow(this.rowData.getCurrentRowNumber()); - } catch (java.io.UnsupportedEncodingException encodingEx) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.39", //$NON-NLS-1$ - new Object[] { this.charEncoding }) //$NON-NLS-1$ - , SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$ + this.deleter.executeUpdate(); + this.rowData.removeRow(this.rowData.getCurrentRowNumber()); + + // position on previous row - Bug#27431 + previous(); + + } + + private synchronized void setParamValue(PreparedStatement ps, int psIdx, + ResultSetRow row, int rsIdx, int sqlType) throws SQLException { + + byte[] val = row.getColumnValue(rsIdx); + if(val == null){ + ps.setNull(psIdx, Types.NULL); + return; } + switch (sqlType) { + case Types.NULL: + ps.setNull(psIdx, Types.NULL); + break; + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + ps.setInt(psIdx, row.getInt(rsIdx)); + break; + case Types.BIGINT: + ps.setLong(psIdx, row.getLong(rsIdx)); + break; + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.DECIMAL: + case Types.NUMERIC: + ps.setString(psIdx, row.getString(rsIdx, this.charEncoding, this.connection)); + break; + case Types.DATE: + ps.setDate(psIdx, row.getDateFast(rsIdx, this.connection, this, this.fastDateCal), this.fastDateCal); + break; + case Types.TIMESTAMP: + ps.setTimestamp(psIdx, row.getTimestampFast(rsIdx, this.fastDateCal, this.defaultTimeZone, false, this.connection, this)); + break; + case Types.TIME: + ps.setTime(psIdx, row.getTimeFast(rsIdx, this.fastDateCal, this.defaultTimeZone, false, this.connection, this)); + break; + case Types.FLOAT: + case Types.DOUBLE: + case Types.REAL: + case Types.BOOLEAN: + ps.setBytesNoEscapeNoQuotes(psIdx, val); + break; + /* default, but also explicitly for following types: + case Types.BINARY: + case Types.BLOB: + */ + default: + ps.setBytes(psIdx, val); + break; + } + } private synchronized void extractDefaultValues() throws SQLException { java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); - + this.defaultColumnValue = new byte[this.fields.length][]; + java.sql.ResultSet columnsResultSet = null; + + for (Map.Entry>> dbEntry : this.databasesUsedToTablesUsed.entrySet()) { + //String databaseName = dbEntry.getKey().toString(); + for (Map.Entry> tableEntry : dbEntry.getValue().entrySet()) { + String tableName = tableEntry.getKey(); + Map columnNamesToIndices = tableEntry.getValue(); - try { - columnsResultSet = dbmd.getColumns(this.catalog, null, - this.tableOnlyName, "%"); //$NON-NLS-1$ + try { + columnsResultSet = dbmd.getColumns(this.catalog, null, + tableName, "%"); //$NON-NLS-1$ - HashMap columnNameToDefaultValueMap = new HashMap( - this.fields.length /* at least this big... */); + while (columnsResultSet.next()) { + String columnName = columnsResultSet.getString("COLUMN_NAME"); //$NON-NLS-1$ + byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF"); //$NON-NLS-1$ - while (columnsResultSet.next()) { - String columnName = columnsResultSet.getString("COLUMN_NAME"); //$NON-NLS-1$ - byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF"); //$NON-NLS-1$ + if (columnNamesToIndices.containsKey(columnName)) { + int localColumnIndex = columnNamesToIndices.get(columnName).intValue(); - columnNameToDefaultValueMap.put(columnName, defaultValue); - } + this.defaultColumnValue[localColumnIndex] = defaultValue; + } // else assert? + } + } finally { + if (columnsResultSet != null) { + columnsResultSet.close(); - int numFields = this.fields.length; - - this.defaultColumnValue = new byte[numFields][]; - - for (int i = 0; i < numFields; i++) { - String defValTableName = this.fields[i].getOriginalName(); - - if ((defValTableName == null) - || (defValTableName.length() == 0)) { - defValTableName = this.fields[i].getName(); - } - - if (defValTableName != null) { - byte[] defaultVal = (byte[]) columnNameToDefaultValueMap - .get(defValTableName); - - this.defaultColumnValue[i] = defaultVal; - } - } - } finally { - if (columnsResultSet != null) { - columnsResultSet.close(); - - columnsResultSet = null; - } + columnsResultSet = null; + } + } + } } } /** * JDBC 2.0 - * + * *

    * Moves to the first row in the result set. *

    - * + * * @return true if on a valid row, false if no rows in the result set. - * + * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWARD_ONLY. @@ -594,7 +605,7 @@ /** * Figure out whether or not this ResultSet is updateable, and if so, * generate the PreparedStatements to support updates. - * + * * @throws SQLException * DOCUMENT ME! * @throws NotUpdatable @@ -610,50 +621,92 @@ String quotedId = getQuotedIdChar(); - if (this.fields[0].getOriginalTableName() != null) { - StringBuffer tableNameBuffer = new StringBuffer(); + Map tableNamesSoFar = null; - String databaseName = this.fields[0].getDatabaseName(); - - if ((databaseName != null) && (databaseName.length() > 0)) { - tableNameBuffer.append(quotedId); - tableNameBuffer.append(databaseName); - tableNameBuffer.append(quotedId); - tableNameBuffer.append('.'); - } - - this.tableOnlyName = this.fields[0].getOriginalTableName(); - - tableNameBuffer.append(quotedId); - tableNameBuffer.append(this.tableOnlyName); - tableNameBuffer.append(quotedId); - - this.qualifiedAndQuotedTableName = tableNameBuffer.toString(); + if (this.connection.lowerCaseTableNames()) { + tableNamesSoFar = new TreeMap(String.CASE_INSENSITIVE_ORDER); + this.databasesUsedToTablesUsed = new TreeMap>>(String.CASE_INSENSITIVE_ORDER); } else { - StringBuffer tableNameBuffer = new StringBuffer(); - - this.tableOnlyName = this.fields[0].getTableName(); - - tableNameBuffer.append(quotedId); - tableNameBuffer.append(this.tableOnlyName); - tableNameBuffer.append(quotedId); - - this.qualifiedAndQuotedTableName = tableNameBuffer.toString(); + tableNamesSoFar = new TreeMap(); + this.databasesUsedToTablesUsed = new TreeMap>>(); } - this.primaryKeyIndicies = new ArrayList(); + this.primaryKeyIndicies = new ArrayList(); StringBuffer fieldValues = new StringBuffer(); StringBuffer keyValues = new StringBuffer(); StringBuffer columnNames = new StringBuffer(); StringBuffer insertPlaceHolders = new StringBuffer(); + StringBuffer allTablesBuf = new StringBuffer(); + Map columnIndicesToTable = new HashMap(); + boolean firstTime = true; boolean keysFirstTime = true; String equalsStr = this.connection.versionMeetsMinimum(3, 23, 0) ? "<=>" : "="; for (int i = 0; i < this.fields.length; i++) { + StringBuffer tableNameBuffer = new StringBuffer(); + Map updColumnNameToIndex = null; + + // FIXME: What about no table? + if (this.fields[i].getOriginalTableName() != null) { + + String databaseName = this.fields[i].getDatabaseName(); + + if ((databaseName != null) && (databaseName.length() > 0)) { + tableNameBuffer.append(quotedId); + tableNameBuffer.append(databaseName); + tableNameBuffer.append(quotedId); + tableNameBuffer.append('.'); + } + + String tableOnlyName = this.fields[i].getOriginalTableName(); + + tableNameBuffer.append(quotedId); + tableNameBuffer.append(tableOnlyName); + tableNameBuffer.append(quotedId); + + String fqTableName = tableNameBuffer.toString(); + + if (!tableNamesSoFar.containsKey(fqTableName)) { + if (!tableNamesSoFar.isEmpty()) { + allTablesBuf.append(','); + } + + allTablesBuf.append(fqTableName); + tableNamesSoFar.put(fqTableName, fqTableName); + } + + columnIndicesToTable.put(Integer.valueOf(i), fqTableName); + + updColumnNameToIndex = getColumnsToIndexMapForTableAndDB(databaseName, tableOnlyName); + } else { + String tableOnlyName = this.fields[i].getTableName(); + + if (tableOnlyName != null) { + tableNameBuffer.append(quotedId); + tableNameBuffer.append(tableOnlyName); + tableNameBuffer.append(quotedId); + + String fqTableName = tableNameBuffer.toString(); + + if (!tableNamesSoFar.containsKey(fqTableName)) { + if (!tableNamesSoFar.isEmpty()) { + allTablesBuf.append(','); + } + + allTablesBuf.append(fqTableName); + tableNamesSoFar.put(fqTableName, fqTableName); + } + + columnIndicesToTable.put(Integer.valueOf(i), fqTableName); + + updColumnNameToIndex = getColumnsToIndexMapForTableAndDB(this.catalog, tableOnlyName); + } + } + String originalColumnName = this.fields[i].getOriginalName(); String columnName = null; @@ -665,18 +718,51 @@ columnName = this.fields[i].getName(); } + if (updColumnNameToIndex != null && columnName != null) { + updColumnNameToIndex.put(columnName, Integer.valueOf(i)); + } + + String originalTableName = this.fields[i].getOriginalTableName(); + String tableName = null; + + if (this.connection.getIO().hasLongColumnInfo() + && (originalTableName != null) + && (originalTableName.length() > 0)) { + tableName = originalTableName; + } else { + tableName = this.fields[i].getTableName(); + } + + StringBuffer fqcnBuf = new StringBuffer(); + String databaseName = this.fields[i].getDatabaseName(); + + if (databaseName != null && databaseName.length() > 0) { + fqcnBuf.append(quotedId); + fqcnBuf.append(databaseName); + fqcnBuf.append(quotedId); + fqcnBuf.append('.'); + } + + fqcnBuf.append(quotedId); + fqcnBuf.append(tableName); + fqcnBuf.append(quotedId); + fqcnBuf.append('.'); + fqcnBuf.append(quotedId); + fqcnBuf.append(columnName); + fqcnBuf.append(quotedId); + + String qualifiedColumnName = fqcnBuf.toString(); + if (this.fields[i].isPrimaryKey()) { - this.primaryKeyIndicies.add(new Integer(i)); + this.primaryKeyIndicies.add(Integer.valueOf(i)); if (!keysFirstTime) { keyValues.append(" AND "); //$NON-NLS-1$ } else { keysFirstTime = false; } - keyValues.append(quotedId); - keyValues.append(columnName); - keyValues.append(quotedId); + keyValues.append(qualifiedColumnName); keyValues.append(equalsStr); keyValues.append("?"); //$NON-NLS-1$ } @@ -692,16 +778,14 @@ insertPlaceHolders.append("?"); //$NON-NLS-1$ - columnNames.append(quotedId); - columnNames.append(columnName); - columnNames.append(quotedId); + columnNames.append(qualifiedColumnName); - fieldValues.append(quotedId); - fieldValues.append(columnName); - fieldValues.append(quotedId); + fieldValues.append(qualifiedColumnName); fieldValues.append("=?"); //$NON-NLS-1$ } + this.qualifiedAndQuotedTableName = allTablesBuf.toString(); + this.updateSQL = "UPDATE " + this.qualifiedAndQuotedTableName + " " //$NON-NLS-1$ //$NON-NLS-2$ + fieldValues.toString() //$NON-NLS-1$ //$NON-NLS-2$ + " WHERE " + keyValues.toString(); //$NON-NLS-1$ @@ -716,6 +800,30 @@ + keyValues.toString(); } + private Map getColumnsToIndexMapForTableAndDB(String databaseName, String tableName) { + Map nameToIndex; + Map> tablesUsedToColumnsMap = this.databasesUsedToTablesUsed.get(databaseName); + + if (tablesUsedToColumnsMap == null) { + if (this.connection.lowerCaseTableNames()) { + tablesUsedToColumnsMap = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + } else { + tablesUsedToColumnsMap = new TreeMap>(); + } + + this.databasesUsedToTablesUsed.put(databaseName, tablesUsedToColumnsMap); + } + + nameToIndex = tablesUsedToColumnsMap.get(tableName); + + if (nameToIndex == null) { + nameToIndex = new HashMap(); + tablesUsedToColumnsMap.put(tableName, nameToIndex); + } + + return nameToIndex; + } + private synchronized SingleByteCharsetConverter getCharConverter() throws SQLException { if (!this.initializedCharConverter) { @@ -734,9 +842,9 @@ /** * JDBC 2.0 Return the concurrency of this result set. The concurrency used * is determined by the statement that created the result set. - * + * * @return the concurrency type, CONCUR_READ_ONLY, etc. - * + * * @exception SQLException * if a database-access error occurs */ @@ -763,7 +871,7 @@ /** * JDBC 2.0 Insert the contents of the insert row into the result set and * the database. Must be on the insert row when this method is called. - * + * * @exception SQLException * if a database-access error occurs, if called when not on * the insert row, or if all non-nullable columns in the @@ -773,7 +881,7 @@ checkClosed(); if (!this.onInsertRow) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.7")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.7"), getExceptionInterceptor()); //$NON-NLS-1$ } this.inserter.executeUpdate(); @@ -794,28 +902,29 @@ // than one auto-increment key (which is the way it is _today_) // if (this.fields[i].isAutoIncrement() && autoIncrementId > 0) { - newRow[i] = String.valueOf(autoIncrementId).getBytes(); + newRow[i] = StringUtils.getBytes(String.valueOf(autoIncrementId)); this.inserter.setBytesNoEscapeNoQuotes(i + 1, newRow[i]); } } - - refreshRow(this.inserter, newRow); - - this.rowData.addRow(newRow); + + ResultSetRow resultSetRow = new ByteArrayRow(newRow, getExceptionInterceptor()); + + refreshRow(this.inserter, resultSetRow); + + this.rowData.addRow(resultSetRow); resetInserter(); } - /** * JDBC 2.0 - * + * *

    * Determine if the cursor is after the last row in the result set. *

    - * + * * @return true if after the last row, false otherwise. Returns false when * the result set contains no rows. - * + * * @exception SQLException * if a database-access error occurs. */ @@ -825,14 +934,14 @@ /** * JDBC 2.0 - * + * *

    * Determine if the cursor is before the first row in the result set. *

    - * + * * @return true if before the first row, false otherwise. Returns false when * the result set contains no rows. - * + * * @exception SQLException * if a database-access error occurs. */ @@ -842,13 +951,13 @@ /** * JDBC 2.0 - * + * *

    * Determine if the cursor is on the first row of the result set. *

    - * + * * @return true if on the first row, false otherwise. - * + * * @exception SQLException * if a database-access error occurs. */ @@ -858,16 +967,16 @@ /** * JDBC 2.0 - * + * *

    * Determine if the cursor is on the last row of the result set. Note: * Calling isLast() may be expensive since the JDBC driver might need to * fetch ahead one row in order to determine whether the current row is the * last row in the result set. *

    - * + * * @return true if on the last row, false otherwise. - * + * * @exception SQLException * if a database-access error occurs. */ @@ -881,13 +990,13 @@ /** * JDBC 2.0 - * + * *

    * Moves to the last row in the result set. *

    - * + * * @return true if on a valid row, false if no rows in the result set. - * + * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWARD_ONLY. @@ -899,7 +1008,7 @@ /** * JDBC 2.0 Move the cursor to the remembered cursor position, usually the * current row. Has no effect unless the cursor is on the insert row. - * + * * @exception SQLException * if a database-access error occurs, or the result set is * not updatable @@ -929,7 +1038,7 @@ * cursor is on the insert row. All of the columns in a result set must be * given a value each time this method is called before calling insertRow(). * UpdateXXX()must be called before getXXX() on a column. - * + * * @exception SQLException * if a database-access error occurs, or the result set is * not updatable @@ -948,12 +1057,12 @@ generateStatements(); } - this.inserter = this.connection + this.inserter = (PreparedStatement) this.connection .clientPrepareStatement(this.insertSQL); if (this.populateInserterWithDefaultValues) { extractDefaultValues(); } - + resetInserter(); } else { resetInserter(); @@ -964,24 +1073,25 @@ this.onInsertRow = true; this.doingUpdates = false; this.savedCurrentRow = this.thisRow; - this.thisRow = new byte[numFields][]; + byte[][] newRowData = new byte[numFields][]; + this.thisRow = new ByteArrayRow(newRowData, getExceptionInterceptor()); for (int i = 0; i < numFields; i++) { if (!this.populateInserterWithDefaultValues) { - this.inserter.setBytesNoEscapeNoQuotes(i + 1, - "DEFAULT".getBytes()); - this.thisRow[i] = null; + this.inserter.setBytesNoEscapeNoQuotes(i + 1, + StringUtils.getBytes("DEFAULT")); + newRowData = null; } else { if (this.defaultColumnValue[i] != null) { Field f = this.fields[i]; - + switch (f.getMysqlType()) { case MysqlDefs.FIELD_TYPE_DATE: case MysqlDefs.FIELD_TYPE_DATETIME: case MysqlDefs.FIELD_TYPE_NEWDATE: case MysqlDefs.FIELD_TYPE_TIME: case MysqlDefs.FIELD_TYPE_TIMESTAMP: - + if (this.defaultColumnValue[i].length > 7 && this.defaultColumnValue[i][0] == (byte) 'C' && this.defaultColumnValue[i][1] == (byte) 'U' @@ -993,40 +1103,44 @@ && this.defaultColumnValue[i][7] == (byte) '_') { this.inserter.setBytesNoEscapeNoQuotes(i + 1, this.defaultColumnValue[i]); - + break; } default: this.inserter.setBytes(i + 1, this.defaultColumnValue[i], false, false); } - + // This value _could_ be changed from a getBytes(), so we // need a copy.... byte[] defaultValueCopy = new byte[this.defaultColumnValue[i].length]; System.arraycopy(defaultColumnValue[i], 0, defaultValueCopy, 0, defaultValueCopy.length); - this.thisRow[i] = defaultValueCopy; + newRowData[i] = defaultValueCopy; } else { this.inserter.setNull(i + 1, java.sql.Types.NULL); - this.thisRow[i] = null; + newRowData[i] = null; } } } } - + + // --------------------------------------------------------------------- + // Updates + // --------------------------------------------------------------------- + /** * A ResultSet is initially positioned before its first row, the first call * to next makes the first row the current row; the second call makes the * second row the current row, etc. - * + * *

    * If an input stream from the previous row is open, it is implicitly * closed. The ResultSet's warning chain is cleared when a new row is read *

    - * + * * @return true if the new current is valid; false if there are no more rows - * + * * @exception SQLException * if a database access error occurs */ @@ -1038,14 +1152,14 @@ * The prev method is not part of JDBC, but because of the architecture of * this driver it is possible to move both forward and backward within the * result set. - * + * *

    * If an input stream from the previous row is open, it is implicitly * closed. The ResultSet's warning chain is cleared when a new row is read *

    - * + * * @return true if the new current is valid; false if there are no more rows - * + * * @exception SQLException * if a database access error occurs */ @@ -1055,18 +1169,18 @@ /** * JDBC 2.0 - * + * *

    * Moves to the previous row in the result set. *

    - * + * *

    * Note: previous() is not the same as relative(-1) since it makes sense to * call previous() when there is no current row. *

    - * + * * @return true if on a valid row, false if off the result set. - * + * * @exception SQLException * if a database-access error occurs, or result set type is * TYPE_FORWAR_DONLY. @@ -1076,25 +1190,26 @@ } /** - * Closes this ResultSet, releasing all resources. + * Closes this ResultSet and releases resources. * * @param calledExplicitly - * was this called from close()? + * was realClose called by the standard ResultSet.close() method, or was it closed internally by the + * driver? * * @throws SQLException * if an error occurs. */ - protected void realClose(boolean calledExplicitly) throws SQLException { + public synchronized void realClose(boolean calledExplicitly) throws SQLException { if (this.isClosed) { return; } - + SQLException sqlEx = null; if (this.useUsageAdvisor) { if ((this.deleter == null) && (this.inserter == null) && (this.refresher == null) && (this.updater == null)) { - this.eventSink = ProfileEventSink.getInstance(this.connection); + this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection); String message = Messages.getString("UpdatableResultSet.34"); //$NON-NLS-1$ @@ -1163,7 +1278,7 @@ * calling updateXXX(), but before calling updateRow() then the updates made * to the row are lost. Calling refreshRow() frequently will likely slow * performance. - * + * * @exception SQLException * if a database-access error occurs, or if called when on * the insert row. @@ -1178,26 +1293,26 @@ } if (this.onInsertRow) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.8")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.8"), getExceptionInterceptor()); //$NON-NLS-1$ } else if (this.rowData.size() == 0) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.9")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.9"), getExceptionInterceptor()); //$NON-NLS-1$ } else if (isBeforeFirst()) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.10")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.10"), getExceptionInterceptor()); //$NON-NLS-1$ } else if (isAfterLast()) { - throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.11")); //$NON-NLS-1$ + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.11"), getExceptionInterceptor()); //$NON-NLS-1$ } refreshRow(this.updater, this.thisRow); } - - private synchronized void refreshRow(PreparedStatement updateInsertStmt, - Object[] rowToRefresh) throws SQLException { + + private synchronized void refreshRow(PreparedStatement updateInsertStmt, + ResultSetRow rowToRefresh) throws SQLException { if (this.refresher == null) { if (this.refreshSQL == null) { generateStatements(); } - this.refresher = this.connection + this.refresher = (PreparedStatement) this.connection .clientPrepareStatement(this.refreshSQL); } @@ -1207,36 +1322,41 @@ if (numKeys == 1) { byte[] dataFrom = null; - int index = ((Integer) this.primaryKeyIndicies.get(0)).intValue(); + int index = this.primaryKeyIndicies.get(0).intValue(); if (!this.doingUpdates && !this.onInsertRow) { - dataFrom = (byte[]) rowToRefresh[index]; + dataFrom = rowToRefresh.getColumnValue(index); } else { dataFrom = updateInsertStmt.getBytesRepresentation(index); // Primary keys not set? if (updateInsertStmt.isNull(index) || (dataFrom.length == 0)) { - dataFrom = (byte[]) rowToRefresh[index]; + dataFrom = rowToRefresh.getColumnValue(index); } else { dataFrom = stripBinaryPrefix(dataFrom); } } - this.refresher.setBytesNoEscape(1, dataFrom); + if (this.fields[index].getvalueNeedsQuoting()) { + this.refresher.setBytesNoEscape(1, dataFrom); + } else { + this.refresher.setBytesNoEscapeNoQuotes(1, dataFrom); + } + } else { for (int i = 0; i < numKeys; i++) { byte[] dataFrom = null; - int index = ((Integer) this.primaryKeyIndicies.get(i)) + int index = this.primaryKeyIndicies.get(i) .intValue(); if (!this.doingUpdates && !this.onInsertRow) { - dataFrom = (byte[]) rowToRefresh[index]; + dataFrom = rowToRefresh.getColumnValue(index); } else { dataFrom = updateInsertStmt.getBytesRepresentation(index); // Primary keys not set? if (updateInsertStmt.isNull(index) || (dataFrom.length == 0)) { - dataFrom = (byte[]) this.thisRow[index]; + dataFrom = rowToRefresh.getColumnValue(index); } else { dataFrom = stripBinaryPrefix(dataFrom); } @@ -1258,15 +1378,15 @@ byte[] val = rs.getBytes(i + 1); if ((val == null) || rs.wasNull()) { - rowToRefresh[i] = null; + rowToRefresh.setColumnValue(i, null); } else { - rowToRefresh[i] = rs.getBytes(i + 1); + rowToRefresh.setColumnValue(i, rs.getBytes(i + 1)); } } } else { throw SQLError.createSQLException(Messages .getString("UpdatableResultSet.12"), //$NON-NLS-1$ - SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); //$NON-NLS-1$ } } finally { if (rs != null) { @@ -1281,26 +1401,26 @@ /** * JDBC 2.0 - * + * *

    * Moves a relative number of rows, either positive or negative. Attempting * to move beyond the first/last row in the result set positions the cursor * before/after the the first/last row. Calling relative(0) is valid, but * does not change the cursor position. *

    - * + * *

    * Note: Calling relative(1) is different than calling next() since is makes * sense to call next() when there is no current row, for example, when the * cursor is positioned before the first row or after the last row of the * result set. *

    - * + * * @param rows * DOCUMENT ME! - * + * * @return true if on a row, false otherwise. - * + * * @exception SQLException * if a database-access error occurs, or there is no current * row, or result set type is TYPE_FORWARD_ONLY. @@ -1322,59 +1442,59 @@ * a visible "hole" in a result set. This method can be used to detect holes * in a result set. The value returned depends on whether or not the result * set can detect deletions. - * + * * @return true if deleted and deletes are detected - * + * * @exception SQLException * if a database-access error occurs * @throws NotImplemented * DOCUMENT ME! - * + * * @see DatabaseMetaData#deletesAreDetected */ public synchronized boolean rowDeleted() throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** * JDBC 2.0 Determine if the current row has been inserted. The value * returned depends on whether or not the result set can detect visible * inserts. - * + * * @return true if inserted and inserts are detected - * + * * @exception SQLException * if a database-access error occurs * @throws NotImplemented * DOCUMENT ME! - * + * * @see DatabaseMetaData#insertsAreDetected */ public synchronized boolean rowInserted() throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** * JDBC 2.0 Determine if the current row has been updated. The value * returned depends on whether or not the result set can detect updates. - * + * * @return true if the row has been visibly updated by the owner or another, * and updates are detected - * + * * @exception SQLException * if a database-access error occurs * @throws NotImplemented * DOCUMENT ME! - * + * * @see DatabaseMetaData#updatesAreDetected */ public synchronized boolean rowUpdated() throws SQLException { - throw new NotImplemented(); + throw SQLError.notImplemented(); } /** * Sets the concurrency type of this result set - * + * * @param concurrencyFlag * the type of concurrency that this ResultSet should support. */ @@ -1399,27 +1519,32 @@ /** * Reset UPDATE prepared statement to value in current row. This_Row MUST * point to current, valid row. - * + * * @throws SQLException * DOCUMENT ME! */ - synchronized void syncUpdate() throws SQLException { + protected synchronized void syncUpdate() throws SQLException { if (this.updater == null) { if (this.updateSQL == null) { generateStatements(); } - this.updater = this.connection + this.updater = (PreparedStatement) this.connection .clientPrepareStatement(this.updateSQL); } int numFields = this.fields.length; this.updater.clearParameters(); for (int i = 0; i < numFields; i++) { - if (this.thisRow[i] != null) { - this.updater.setBytes(i + 1, (byte[]) this.thisRow[i], - this.fields[i].isBinary(), false); + if (this.thisRow.getColumnValue(i) != null) { + + if (this.fields[i].getvalueNeedsQuoting()) { + this.updater.setBytes(i + 1, this.thisRow.getColumnValue(i), + this.fields[i].isBinary(), false); + } else { + this.updater.setBytesNoEscapeNoQuotes(i + 1, this.thisRow.getColumnValue(i)); + } } else { this.updater.setNull(i + 1, 0); } @@ -1428,20 +1553,14 @@ int numKeys = this.primaryKeyIndicies.size(); if (numKeys == 1) { - int index = ((Integer) this.primaryKeyIndicies.get(0)).intValue(); - byte[] keyData = (byte[]) this.thisRow[index]; - this.updater.setBytes(numFields + 1, keyData, false, false); + int index = this.primaryKeyIndicies.get(0).intValue(); + this.setParamValue(this.updater, numFields + 1, this.thisRow, index , + this.fields[index].getSQLType()); } else { for (int i = 0; i < numKeys; i++) { - byte[] currentVal = (byte[]) this.thisRow[((Integer) this.primaryKeyIndicies - .get(i)).intValue()]; - - if (currentVal != null) { - this.updater.setBytes(numFields + i + 1, currentVal, false, - false); - } else { - this.updater.setNull(numFields + i + 1, 0); - } + int idx = this.primaryKeyIndicies.get(i).intValue(); + this.setParamValue(this.updater, numFields + i + 1, this.thisRow, + idx , this.fields[idx].getSQLType()); } } } @@ -1452,14 +1571,14 @@ * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value * @param length * the length of the stream - * + * * @exception SQLException * if a database-access error occurs */ @@ -1474,7 +1593,7 @@ this.updater.setAsciiStream(columnIndex, x, length); } else { this.inserter.setAsciiStream(columnIndex, x, length); - this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; + this.thisRow.setColumnValue(columnIndex - 1, STREAM_DATA_MARKER); } } @@ -1484,14 +1603,14 @@ * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. - * + * * @param columnName * the name of the column * @param x * the new column value * @param length * of the stream - * + * * @exception SQLException * if a database-access error occurs */ @@ -1505,12 +1624,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1527,9 +1646,9 @@ this.inserter.setBigDecimal(columnIndex, x); if (x == null) { - this.thisRow[columnIndex - 1] = null; + this.thisRow.setColumnValue(columnIndex - 1, null); } else { - this.thisRow[columnIndex - 1] = x.toString().getBytes(); + this.thisRow.setColumnValue(columnIndex - 1, StringUtils.getBytes(x.toString())); } } } @@ -1539,12 +1658,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1559,14 +1678,14 @@ * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value * @param length * the length of the stream - * + * * @exception SQLException * if a database-access error occurs */ @@ -1583,9 +1702,9 @@ this.inserter.setBinaryStream(columnIndex, x, length); if (x == null) { - this.thisRow[columnIndex - 1] = null; + this.thisRow.setColumnValue(columnIndex - 1, null); } else { - this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; + this.thisRow.setColumnValue(columnIndex - 1, STREAM_DATA_MARKER); } } } @@ -1596,14 +1715,14 @@ * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. - * + * * @param columnName * the name of the column * @param x * the new column value * @param length * of the stream - * + * * @exception SQLException * if a database-access error occurs */ @@ -1613,7 +1732,7 @@ } /** - * @see ResultSet#updateBlob(int, Blob) + * @see ResultSetInternalMethods#updateBlob(int, Blob) */ public synchronized void updateBlob(int columnIndex, java.sql.Blob blob) throws SQLException { @@ -1628,15 +1747,15 @@ this.inserter.setBlob(columnIndex, blob); if (blob == null) { - this.thisRow[columnIndex - 1] = null; + this.thisRow.setColumnValue(columnIndex - 1, null); } else { - this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; + this.thisRow.setColumnValue(columnIndex - 1, STREAM_DATA_MARKER); } } } /** - * @see ResultSet#updateBlob(String, Blob) + * @see ResultSetInternalMethods#updateBlob(String, Blob) */ public synchronized void updateBlob(String columnName, java.sql.Blob blob) throws SQLException { @@ -1648,12 +1767,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1669,8 +1788,8 @@ } else { this.inserter.setBoolean(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -1679,12 +1798,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1698,12 +1817,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1719,8 +1838,8 @@ } else { this.inserter.setByte(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -1729,12 +1848,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1748,12 +1867,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1769,7 +1888,7 @@ } else { this.inserter.setBytes(columnIndex, x); - this.thisRow[columnIndex - 1] = x; + this.thisRow.setColumnValue(columnIndex - 1, x); } } @@ -1778,12 +1897,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1798,14 +1917,14 @@ * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value * @param length * the length of the stream - * + * * @exception SQLException * if a database-access error occurs */ @@ -1822,9 +1941,9 @@ this.inserter.setCharacterStream(columnIndex, x, length); if (x == null) { - this.thisRow[columnIndex - 1] = null; + this.thisRow.setColumnValue(columnIndex - 1, null); } else { - this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; + this.thisRow.setColumnValue(columnIndex - 1, STREAM_DATA_MARKER); } } } @@ -1835,14 +1954,14 @@ * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. - * + * * @param columnName * the name of the column * @param reader * the new column value * @param length * of the stream - * + * * @exception SQLException * if a database-access error occurs */ @@ -1852,7 +1971,7 @@ } /** - * @see ResultSet#updateClob(int, Clob) + * @see ResultSetInternalMethods#updateClob(int, Clob) */ public void updateClob(int columnIndex, java.sql.Clob clob) throws SQLException { @@ -1869,12 +1988,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1890,8 +2009,8 @@ } else { this.inserter.setDate(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -1900,12 +2019,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1919,12 +2038,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1940,8 +2059,8 @@ } else { this.inserter.setDouble(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -1950,12 +2069,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1969,12 +2088,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -1990,8 +2109,8 @@ } else { this.inserter.setFloat(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2000,12 +2119,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2019,12 +2138,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2040,8 +2159,8 @@ } else { this.inserter.setInt(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2050,12 +2169,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2069,12 +2188,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2090,8 +2209,8 @@ } else { this.inserter.setLong(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2100,12 +2219,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2119,10 +2238,10 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... - * + * * @exception SQLException * if a database-access error occurs */ @@ -2137,7 +2256,7 @@ } else { this.inserter.setNull(columnIndex, 0); - this.thisRow[columnIndex - 1] = null; + this.thisRow.setColumnValue(columnIndex - 1, null); } } @@ -2146,10 +2265,10 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column - * + * * @exception SQLException * if a database-access error occurs */ @@ -2162,12 +2281,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2183,8 +2302,8 @@ } else { this.inserter.setObject(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2193,7 +2312,7 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x @@ -2202,7 +2321,7 @@ * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types * this is the number of digits after the decimal. For all other * types this value will be ignored. - * + * * @exception SQLException * if a database-access error occurs */ @@ -2218,8 +2337,8 @@ } else { this.inserter.setObject(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2228,12 +2347,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2247,7 +2366,7 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x @@ -2256,7 +2375,7 @@ * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types * this is the number of digits after the decimal. For all other * types this value will be ignored. - * + * * @exception SQLException * if a database-access error occurs */ @@ -2268,7 +2387,7 @@ /** * JDBC 2.0 Update the underlying database with the new contents of the * current row. Cannot be called when on the insert row. - * + * * @exception SQLException * if a database-access error occurs, or if called when on * the insert row @@ -2284,6 +2403,8 @@ this.updater.executeUpdate(); refreshRow(); this.doingUpdates = false; + } else if (this.onInsertRow) { + throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.44"), getExceptionInterceptor()); //$NON-NLS-1$ } // @@ -2297,12 +2418,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2318,8 +2439,8 @@ } else { this.inserter.setShort(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2328,12 +2449,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2347,19 +2468,19 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ public synchronized void updateString(int columnIndex, String x) throws SQLException { checkClosed(); - + if (!this.onInsertRow) { if (!this.doingUpdates) { this.doingUpdates = true; @@ -2371,15 +2492,15 @@ this.inserter.setString(columnIndex, x); if (x == null) { - this.thisRow[columnIndex - 1] = null; + this.thisRow.setColumnValue(columnIndex - 1, null); } else { if (getCharConverter() != null) { - this.thisRow[columnIndex - 1] = StringUtils.getBytes(x, + this.thisRow.setColumnValue(columnIndex - 1, StringUtils.getBytes(x, this.charConverter, this.charEncoding, this.connection.getServerCharacterEncoding(), - this.connection.parserKnowsUnicode()); + this.connection.parserKnowsUnicode(), getExceptionInterceptor())); } else { - this.thisRow[columnIndex - 1] = x.getBytes(); + this.thisRow.setColumnValue(columnIndex - 1, StringUtils.getBytes(x)); } } } @@ -2390,12 +2511,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2409,12 +2530,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2430,8 +2551,8 @@ } else { this.inserter.setTime(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2440,12 +2561,12 @@ * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2459,12 +2580,12 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnIndex * the first column is 1, the second is 2, ... * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ @@ -2480,8 +2601,8 @@ } else { this.inserter.setTimestamp(columnIndex, x); - this.thisRow[columnIndex - 1] = this.inserter - .getBytesRepresentation(columnIndex - 1); + this.thisRow.setColumnValue(columnIndex - 1, this.inserter + .getBytesRepresentation(columnIndex - 1)); } } @@ -2490,17 +2611,17 @@ * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the database. - * + * * @param columnName * the name of the column * @param x * the new column value - * + * * @exception SQLException * if a database-access error occurs */ public synchronized void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException { updateTimestamp(findColumn(columnName), x); } -} \ No newline at end of file +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/Util.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/Util.java (.../Util.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/Util.java (.../Util.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,34 +1,42 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.ObjectInputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; import java.util.TimeZone; /** @@ -37,20 +45,68 @@ * @author Mark Matthews */ public class Util { + protected final static Method systemNanoTimeMethod; - protected static Method systemNanoTimeMethod; - - private static boolean isColdFusion = false; - static { + Method aMethod; + try { - systemNanoTimeMethod = System.class.getMethod("nanoTime", null); + aMethod = System.class.getMethod("nanoTime", (Class[])null); } catch (SecurityException e) { - systemNanoTimeMethod = null; + aMethod = null; } catch (NoSuchMethodException e) { - systemNanoTimeMethod = null; + aMethod = null; } + systemNanoTimeMethod = aMethod; + } + + public static boolean nanoTimeAvailable() { + return systemNanoTimeMethod != null; + } + + private static Method CAST_METHOD; + + // cache this ourselves, as the method call is statically-synchronized in + // all but JDK6! + + private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault(); + + static final TimeZone getDefaultTimeZone() { + return (TimeZone) DEFAULT_TIMEZONE.clone(); + } + + class RandStructcture { + long maxValue; + + double maxValueDbl; + + long seed1; + + long seed2; + } + + private static Util enclosingInstance = new Util(); + + private static boolean isJdbc4 = false; + + private static boolean isColdFusion = false; + + static { + try { + CAST_METHOD = Class.class.getMethod("cast", + new Class[] { Object.class }); + } catch (Throwable t) { + // ignore - not available in this VM + } + + try { + Class.forName("java.sql.NClob"); + isJdbc4 = true; + } catch (Throwable t) { + isJdbc4 = false; + } + // // Detect the ColdFusion MX environment // @@ -66,38 +122,20 @@ isColdFusion = false; } } + + // ~ Methods + // ---------------------------------------------------------------- + + public static boolean isJdbc4() { + return isJdbc4; + } public static boolean isColdFusion() { return isColdFusion; } - - protected static boolean nanoTimeAvailable() { - return systemNanoTimeMethod != null; - } - - // cache this ourselves, as the method call is statically-synchronized in all but JDK6! - - private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault(); - - static final TimeZone getDefaultTimeZone() { - return (TimeZone)DEFAULT_TIMEZONE.clone(); - } - - class RandStructcture { - long maxValue; - double maxValueDbl; - - long seed1; - - long seed2; - } - - - private static Util enclosingInstance = new Util(); - // Right from Monty's code - static String newCrypt(String password, String seed) { + public static String newCrypt(String password, String seed) { byte b; double d; @@ -156,7 +194,7 @@ return result; } - static String oldCrypt(String password, String seed) { + public static String oldCrypt(String password, String seed) { long hp; long hm; long s1; @@ -291,7 +329,7 @@ to[i] ^= extra; } - val = new String(to); + val = StringUtils.toString(to); } return val; @@ -337,27 +375,110 @@ return traceBuf.toString(); } - + + public static Object getInstance(String className, Class[] argTypes, + Object[] args, ExceptionInterceptor exceptionInterceptor) throws SQLException { + + try { + return handleNewInstance(Class.forName(className).getConstructor( + argTypes), args, exceptionInterceptor); + } catch (SecurityException e) { + throw SQLError.createSQLException( + "Can't instantiate required class", + SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); + } catch (NoSuchMethodException e) { + throw SQLError.createSQLException( + "Can't instantiate required class", + SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); + } catch (ClassNotFoundException e) { + throw SQLError.createSQLException( + "Can't instantiate required class", + SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); + } + } + /** + * Handles constructing new instance with the given constructor and wrapping + * (or not, as required) the exceptions that could possibly be generated + */ + public static final Object handleNewInstance(Constructor ctor, Object[] args, ExceptionInterceptor exceptionInterceptor) + throws SQLException { + try { + + return ctor.newInstance(args); + } catch (IllegalArgumentException e) { + throw SQLError.createSQLException( + "Can't instantiate required class", + SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); + } catch (InstantiationException e) { + throw SQLError.createSQLException( + "Can't instantiate required class", + SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); + } catch (IllegalAccessException e) { + throw SQLError.createSQLException( + "Can't instantiate required class", + SQLError.SQL_STATE_GENERAL_ERROR, e, exceptionInterceptor); + } catch (InvocationTargetException e) { + Throwable target = e.getTargetException(); + + if (target instanceof SQLException) { + throw (SQLException) target; + } + + if (target instanceof ExceptionInInitializerError) { + target = ((ExceptionInInitializerError) target).getException(); + } + + throw SQLError.createSQLException(target.toString(), + SQLError.SQL_STATE_GENERAL_ERROR, + target, exceptionInterceptor); + } + } + + /** * Does a network interface exist locally with the given hostname? * - * @param hostname the hostname (or IP address in string form) to check - * @return true if it exists, false if no, or unable to determine due to VM version support - * of java.net.NetworkInterface + * @param hostname + * the hostname (or IP address in string form) to check + * @return true if it exists, false if no, or unable to determine due to VM + * version support of java.net.NetworkInterface */ public static boolean interfaceExists(String hostname) { try { - Class networkInterfaceClass = Class.forName("java.net.NetworkInterface"); - return networkInterfaceClass.getMethod("getByName", null).invoke(networkInterfaceClass, new Object[] { hostname }) != null; + Class networkInterfaceClass = Class + .forName("java.net.NetworkInterface"); + return networkInterfaceClass.getMethod("getByName", (Class[])null).invoke( + networkInterfaceClass, new Object[] { hostname }) != null; } catch (Throwable t) { return false; } } + /** + * Reflexive access on JDK-1.5's Class.cast() method so we don't have to + * move that out into separate classes built for JDBC-4.0. + * + * @param invokeOn + * @param toCast + * @return + */ + public static Object cast(Object invokeOn, Object toCast) { + if (CAST_METHOD != null) { + try { + return CAST_METHOD.invoke(invokeOn, new Object[] { toCast }); + } catch (Throwable t) { + return null; + } + } + + return null; + } + public static long getCurrentTimeNanosOrMillis() { if (systemNanoTimeMethod != null) { try { - return ((Long)systemNanoTimeMethod.invoke(null, null)).longValue(); + return ((Long) systemNanoTimeMethod.invoke(null, (Object[])null)) + .longValue(); } catch (IllegalArgumentException e) { // ignore - fall through to currentTimeMillis() } catch (IllegalAccessException e) { @@ -366,7 +487,133 @@ // ignore - fall through to currentTimeMillis() } } - + return System.currentTimeMillis(); } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs) + throws SQLException { + while (rs.next()) { + mappedValues.put(rs.getObject(1), rs.getObject(2)); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs, int key, int value) + throws SQLException { + while (rs.next()) { + mappedValues.put(rs.getObject(key), rs.getObject(value)); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs, String key, String value) + throws SQLException { + while (rs.next()) { + mappedValues.put(rs.getObject(key), rs.getObject(value)); + } + } + + public static Map calculateDifferences(Map map1, Map map2) { + Map diffMap = new HashMap(); + + for (Map.Entry entry : map1.entrySet()) { + Object key = entry.getKey(); + + Number value1 = null; + Number value2 = null; + + if (entry.getValue() instanceof Number) { + + value1 = (Number) entry.getValue(); + value2 = (Number) map2.get(key); + } else { + try { + value1 = new Double(entry.getValue().toString()); + value2 = new Double(map2.get(key).toString()); + } catch (NumberFormatException nfe) { + continue; + } + } + + if (value1.equals(value2)) { + continue; + } + + if (value1 instanceof Byte) { + diffMap.put(key, Byte.valueOf( + (byte) (((Byte) value2).byteValue() - ((Byte) value1) + .byteValue()))); + } else if (value1 instanceof Short) { + diffMap.put(key, Short.valueOf((short) (((Short) value2) + .shortValue() - ((Short) value1).shortValue()))); + } else if (value1 instanceof Integer) { + diffMap.put(key, Integer.valueOf( + (((Integer) value2).intValue() - ((Integer) value1) + .intValue()))); + } else if (value1 instanceof Long) { + diffMap.put(key, Long.valueOf( + (((Long) value2).longValue() - ((Long) value1) + .longValue()))); + } else if (value1 instanceof Float) { + diffMap.put(key, Float.valueOf(((Float) value2).floatValue() + - ((Float) value1).floatValue())); + } else if (value1 instanceof Double) { + diffMap.put(key, Double.valueOf( + (((Double) value2).shortValue() - ((Double) value1) + .shortValue()))); + } else if (value1 instanceof BigDecimal) { + diffMap.put(key, ((BigDecimal) value2) + .subtract((BigDecimal) value1)); + } else if (value1 instanceof BigInteger) { + diffMap.put(key, ((BigInteger) value2) + .subtract((BigInteger) value1)); + } + } + + return diffMap; + } + + /** + * Returns initialized instances of classes listed in extensionClassNames. + * There is no need to call Extension.init() method after that if you don't change connection or properties. + * + * @param conn + * @param props + * @param extensionClassNames + * @param errorMessageKey + * @param exceptionInterceptor + * @return + * @throws SQLException + */ + public static List loadExtensions(Connection conn, + Properties props, String extensionClassNames, + String errorMessageKey, ExceptionInterceptor exceptionInterceptor) throws SQLException { + List extensionList = new LinkedList(); + + List interceptorsToCreate = StringUtils.split(extensionClassNames, ",", true); + + String className = null; + + try { + for (int i = 0, s = interceptorsToCreate.size(); i < s; i++) { + className = interceptorsToCreate.get(i); + Extension extensionInstance = (Extension) Class.forName( + className).newInstance(); + extensionInstance.init(conn, props); + + extensionList.add(extensionInstance); + } + } catch (Throwable t) { + SQLException sqlEx = SQLError.createSQLException(Messages + .getString(errorMessageKey, new Object[] { className }), exceptionInterceptor); + sqlEx.initCause(t); + + throw sqlEx; + } + + return extensionList; + } + } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/V1toV2StatementInterceptorAdapter.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/V1toV2StatementInterceptorAdapter.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/V1toV2StatementInterceptorAdapter.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,61 @@ +/* + Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc; + +import java.sql.SQLException; +import java.util.Properties; + +public class V1toV2StatementInterceptorAdapter implements StatementInterceptorV2 { + private final StatementInterceptor toProxy; + + public V1toV2StatementInterceptorAdapter(StatementInterceptor toProxy) { + this.toProxy = toProxy; + } + public ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection, + int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, + SQLException statementException) throws SQLException { + return toProxy.postProcess(sql, interceptedStatement, originalResultSet, connection); + } + + public void destroy() { + toProxy.destroy(); + } + + public boolean executeTopLevelOnly() { + return toProxy.executeTopLevelOnly(); + } + + public void init(Connection conn, Properties props) throws SQLException { + toProxy.init(conn, props); + } + + public ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException { + return toProxy.preProcess(sql, interceptedStatement, connection); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/WatchableOutputStream.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/WatchableOutputStream.java (.../WatchableOutputStream.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/WatchableOutputStream.java (.../WatchableOutputStream.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.ByteArrayOutputStream; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/WatchableWriter.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/WatchableWriter.java (.../WatchableWriter.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/WatchableWriter.java (.../WatchableWriter.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; import java.io.CharArrayWriter; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/WriterWatcher.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/WriterWatcher.java (.../WriterWatcher.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/WriterWatcher.java (.../WriterWatcher.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc; /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlClearPasswordPlugin.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlClearPasswordPlugin.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlClearPasswordPlugin.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,83 @@ +/* + Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.authentication; + +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import com.mysql.jdbc.AuthenticationPlugin; +import com.mysql.jdbc.Buffer; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.StringUtils; + +/** + * MySQL Clear Password Authentication Plugin + * + */ +public class MysqlClearPasswordPlugin implements AuthenticationPlugin { + + private String password = null; + + public void init(Connection conn, Properties props) throws SQLException { + } + + public void destroy() { + this.password = null; + } + + public String getProtocolPluginName() { + return "mysql_clear_password"; + } + + public boolean requiresConfidentiality() { + return true; + } + + public boolean isReusable() { + return true; + } + + public void setAuthenticationParameters(String user, String password) { + this.password = password; + } + + public boolean nextAuthenticationStep(Buffer fromServer, List toServer) throws SQLException { + toServer.clear(); + + Buffer bresp = new Buffer(StringUtils.getBytes(this.password != null ? this.password : "")); + + bresp.setPosition(bresp.getBufLength()); + int oldBufLength = bresp.getBufLength(); + + bresp.writeByte((byte)0); + + bresp.setBufLength(oldBufLength + 1); + bresp.setPosition(0); + + toServer.add(bresp); + return true; + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlNativePasswordPlugin.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlNativePasswordPlugin.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlNativePasswordPlugin.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,107 @@ +/* + Copyright (c) 2012, 2014 Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.authentication; + +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import com.mysql.jdbc.AuthenticationPlugin; +import com.mysql.jdbc.Buffer; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.Messages; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Security; + +/** + * MySQL Native Password Authentication Plugin + * + */ +public class MysqlNativePasswordPlugin implements AuthenticationPlugin { + + private Connection connection; + private Properties properties; + private String password = null; + + public void init(Connection conn, Properties props) throws SQLException { + this.connection = conn; + this.properties = props; + } + + public void destroy() { + this.password = null; + } + + public String getProtocolPluginName() { + return "mysql_native_password"; + } + + public boolean requiresConfidentiality() { + return false; + } + + public boolean isReusable() { + return true; + } + + public void setAuthenticationParameters(String user, String password) { + this.password = password; + } + + public boolean nextAuthenticationStep(Buffer fromServer, List toServer) throws SQLException { + + try { + toServer.clear(); + + Buffer bresp = null; + + String pwd = this.password; + if (pwd == null) { + pwd = this.properties.getProperty("password"); + } + + if (fromServer == null || pwd == null || pwd.length() == 0) { + bresp = new Buffer(new byte[0]); + } else { + bresp = new Buffer(Security.scramble411(pwd, fromServer.readString(), + this.connection.getPasswordCharacterEncoding())); + } + toServer.add(bresp); + + } catch (NoSuchAlgorithmException nse) { + throw SQLError.createSQLException(Messages.getString("MysqlIO.95") //$NON-NLS-1$ + +Messages.getString("MysqlIO.96"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, null); + } catch (UnsupportedEncodingException e) { + throw SQLError.createSQLException(Messages.getString("MysqlIO.95") //$NON-NLS-1$ + +Messages.getString("MysqlIO.96"), //$NON-NLS-1$ + SQLError.SQL_STATE_GENERAL_ERROR, null); + } + + return true; + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlOldPasswordPlugin.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlOldPasswordPlugin.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/MysqlOldPasswordPlugin.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,94 @@ +/* + Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.authentication; + +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import com.mysql.jdbc.AuthenticationPlugin; +import com.mysql.jdbc.Buffer; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.StringUtils; +import com.mysql.jdbc.Util; + +/** + * MySQL Native Old-Password Authentication Plugin + * + */ +public class MysqlOldPasswordPlugin implements AuthenticationPlugin { + + private Properties properties; + private String password = null; + + public void init(Connection conn, Properties props) throws SQLException { + this.properties = props; + } + + public void destroy() { + this.password = null; + } + + public String getProtocolPluginName() { + return "mysql_old_password"; + } + + public boolean requiresConfidentiality() { + return false; + } + + public boolean isReusable() { + return true; + } + + public void setAuthenticationParameters(String user, String password) { + this.password = password; + } + + public boolean nextAuthenticationStep(Buffer fromServer, List toServer) throws SQLException { + toServer.clear(); + + Buffer bresp = null; + + String pwd = this.password; + if (pwd == null) { + pwd = this.properties.getProperty("password"); + } + + bresp = new Buffer(StringUtils.getBytes( fromServer == null || pwd == null || pwd.length() == 0 ? "" : Util.newCrypt(pwd, fromServer.readString().substring(0, 8)) )); + + bresp.setPosition(bresp.getBufLength()); + int oldBufLength = bresp.getBufLength(); + + bresp.writeByte((byte)0); + + bresp.setBufLength(oldBufLength + 1); + bresp.setPosition(0); + + toServer.add(bresp); + + return true; + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/Sha256PasswordPlugin.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/Sha256PasswordPlugin.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/authentication/Sha256PasswordPlugin.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,192 @@ +/* + Copyright (c) 2012, 2014 Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.authentication; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import com.mysql.jdbc.AuthenticationPlugin; +import com.mysql.jdbc.Buffer; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ExportControlled; +import com.mysql.jdbc.Messages; +import com.mysql.jdbc.MySQLConnection; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Security; +import com.mysql.jdbc.StringUtils; + +/** + * MySQL Clear Password Authentication Plugin + * + */ +public class Sha256PasswordPlugin implements AuthenticationPlugin { + + private Connection connection; + private String password = null; + private String seed = null; + private boolean publicKeyRequested = false; + private String publicKeyString = null; + + public void init(Connection conn, Properties props) throws SQLException { + this.connection = conn; + + String pkURL = connection.getServerRSAPublicKeyFile(); + if (pkURL != null) { + this.publicKeyString = readRSAKey(this.connection, pkURL); + } + } + + public void destroy() { + this.connection = null; + this.password = null; + this.seed = null; + } + + public String getProtocolPluginName() { + return "sha256_password"; + } + + public boolean requiresConfidentiality() { + return false; + } + + public boolean isReusable() { + return true; + } + + public void setAuthenticationParameters(String user, String password) { + this.password = password; + } + + public boolean nextAuthenticationStep(Buffer fromServer, List toServer) throws SQLException { + toServer.clear(); + + if (((MySQLConnection) connection).getIO().isSSLEstablished()) { + // allow plain text over SSL + Buffer bresp = new Buffer(StringUtils.getBytes(this.password != null ? this.password : "")); + bresp.setPosition(bresp.getBufLength()); + int oldBufLength = bresp.getBufLength(); + bresp.writeByte((byte) 0); + bresp.setBufLength(oldBufLength + 1); + bresp.setPosition(0); + toServer.add(bresp); + + } else if (this.connection.getServerRSAPublicKeyFile() != null) { + // encrypt with given key, don't use "Public Key Retrieval" + this.seed = fromServer.readString(); + Buffer bresp = new Buffer(encryptPassword(this.password, this.seed, this.connection, this.publicKeyString)); + toServer.add(bresp); + + } else { + if (!this.connection.getAllowPublicKeyRetrieval()) { + throw SQLError.createSQLException( + Messages.getString("Sha256PasswordPlugin.2"), + SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, + connection.getExceptionInterceptor()); + } + + // We must request the public key from the server to encrypt the password + if (this.publicKeyRequested) { + // read key response + Buffer bresp = new Buffer(encryptPassword(this.password, this.seed, this.connection, fromServer.readString())); + toServer.add(bresp); + this.publicKeyRequested = false; + } else { + // build and send Public Key Retrieval packet + this.seed = fromServer.readString(); + Buffer bresp = new Buffer(new byte[] { 1 }); + toServer.add(bresp); + this.publicKeyRequested = true; + } + } + return true; + } + + private static byte[] encryptPassword(String password, String seed, Connection connection, String key) throws SQLException { + byte[] input = StringUtils.getBytesNullTerminated(password != null ? password : ""); + byte[] mysqlScrambleBuff = new byte[input.length]; + Security.xorString(input, mysqlScrambleBuff, seed.getBytes(), input.length); + return ExportControlled.encryptWithRSAPublicKey( + mysqlScrambleBuff, + ExportControlled.decodeRSAPublicKey(key, ((MySQLConnection) connection).getExceptionInterceptor()), + ((MySQLConnection) connection).getExceptionInterceptor()); + } + + private static String readRSAKey(Connection connection, String pkPath) throws SQLException { + String res = null; + byte[] fileBuf = new byte[2048]; + + BufferedInputStream fileIn = null; + + try { + File f = new File(pkPath); + String canonicalPath = f.getCanonicalPath(); + fileIn = new BufferedInputStream(new FileInputStream(canonicalPath)); + + int bytesRead = 0; + + StringBuffer sb = new StringBuffer(); + while ((bytesRead = fileIn.read(fileBuf)) != -1) { + sb.append(StringUtils.toAsciiString(fileBuf, 0, bytesRead)); + } + res = sb.toString(); + + } catch (IOException ioEx) { + + if (connection.getParanoid()) { + throw SQLError.createSQLException( + Messages.getString("Sha256PasswordPlugin.0", new Object[]{""}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + connection.getExceptionInterceptor()); + } + throw SQLError.createSQLException( + Messages.getString("Sha256PasswordPlugin.0", new Object[]{"'"+pkPath+"'"}), + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, + ioEx, + connection.getExceptionInterceptor()); + + } finally { + if (fileIn != null) { + try { + fileIn.close(); + } catch (Exception ex) { + SQLException sqlEx = SQLError.createSQLException( + Messages.getString("Sha256PasswordPlugin.1"), + SQLError.SQL_STATE_GENERAL_ERROR, ex, + connection.getExceptionInterceptor()); + + throw sqlEx; + } + } + } + + return res; + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/3-0-Compat.properties =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/3-0-Compat.properties (.../3-0-Compat.properties) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/3-0-Compat.properties (.../3-0-Compat.properties) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -15,4 +15,5 @@ autoClosePStmtStreams=true processEscapeCodesForPrepStmts=false useFastDateParsing=false -populateInsertRowWithDefaultValues=false \ No newline at end of file +populateInsertRowWithDefaultValues=false +useDirectRowUnpack=false \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/5-0-Compat.properties =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/5-0-Compat.properties (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/5-0-Compat.properties (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,6 @@ +# +# Settings to maintain Connector/J 5.0.x compatibility +# (as much as it can be) +# + +useDirectRowUnpack=false \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/fullDebug.properties =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/fullDebug.properties (.../fullDebug.properties) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/fullDebug.properties (.../fullDebug.properties) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,6 +1,6 @@ # Settings for 'max-debug' style situations profileSQL=true -gatherPerMetrics=true +gatherPerfMetrics=true useUsageAdvisor=true logSlowQueries=true explainSlowQueries=true \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/maxPerformance.properties =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/maxPerformance.properties (.../maxPerformance.properties) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/configs/maxPerformance.properties (.../maxPerformance.properties) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -9,7 +9,7 @@ # restarting the application using this configuration bundle. cachePrepStmts=true -cacheCallableStatements=true +cacheCallableStmts=true cacheServerConfiguration=true @@ -26,4 +26,9 @@ # Can cause high-GC pressure if timeouts are used on every # query -enableQueryTimeouts=false \ No newline at end of file +enableQueryTimeouts=false + +# Bypass connection attribute handling during connection +# setup +connectionAttributes=none + Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/DeadlockTimeoutRollbackMarker.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/DeadlockTimeoutRollbackMarker.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/DeadlockTimeoutRollbackMarker.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,31 @@ +/* + Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions; + +/** + * Marker interface for exceptions that are caused by deadlock/wait timeout + */ +public interface DeadlockTimeoutRollbackMarker { + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLDataException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLDataException.java (.../MySQLDataException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLDataException.java (.../MySQLDataException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,32 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLDataException extends MySQLNonTransientException { + static final long serialVersionUID = 4317904269797988676L; + public MySQLDataException() { super(); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLIntegrityConstraintViolationException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLIntegrityConstraintViolationException.java (.../MySQLIntegrityConstraintViolationException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLIntegrityConstraintViolationException.java (.../MySQLIntegrityConstraintViolationException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,33 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLIntegrityConstraintViolationException extends MySQLNonTransientException { + static final long serialVersionUID = -5528363270635808904L; + public MySQLIntegrityConstraintViolationException() { super(); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLInvalidAuthorizationSpecException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLInvalidAuthorizationSpecException.java (.../MySQLInvalidAuthorizationSpecException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLInvalidAuthorizationSpecException.java (.../MySQLInvalidAuthorizationSpecException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,33 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLInvalidAuthorizationSpecException extends MySQLNonTransientException { + static final long serialVersionUID = 6878889837492500030L; + public MySQLInvalidAuthorizationSpecException() { super(); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLNonTransientConnectionException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLNonTransientConnectionException.java (.../MySQLNonTransientConnectionException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLNonTransientConnectionException.java (.../MySQLNonTransientConnectionException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,33 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLNonTransientConnectionException extends MySQLNonTransientException { + static final long serialVersionUID = -3050543822763367670L; + public MySQLNonTransientConnectionException() { super(); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLNonTransientException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLNonTransientException.java (.../MySQLNonTransientException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLNonTransientException.java (.../MySQLNonTransientException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,32 +1,34 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; import java.sql.SQLException; public class MySQLNonTransientException extends SQLException { + static final long serialVersionUID = -8714521137552613517L; + public MySQLNonTransientException() { super(); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLQueryInterruptedException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLQueryInterruptedException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLQueryInterruptedException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions; + +public class MySQLQueryInterruptedException extends MySQLNonTransientException { + + private static final long serialVersionUID = -8714521137662613517L; + + public MySQLQueryInterruptedException() { + super(); + } + + public MySQLQueryInterruptedException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLQueryInterruptedException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLQueryInterruptedException(String reason) { + super(reason); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLStatementCancelledException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLStatementCancelledException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLStatementCancelledException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,45 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions; + +public class MySQLStatementCancelledException extends MySQLNonTransientException { + + static final long serialVersionUID = -8762717748377197378L; + + public MySQLStatementCancelledException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLStatementCancelledException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLStatementCancelledException(String reason) { + super(reason); + } + + public MySQLStatementCancelledException() { + super("Statement cancelled due to client request"); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLSyntaxErrorException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLSyntaxErrorException.java (.../MySQLSyntaxErrorException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLSyntaxErrorException.java (.../MySQLSyntaxErrorException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,32 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLSyntaxErrorException extends MySQLNonTransientException { + static final long serialVersionUID = 6919059513432113764L; + public MySQLSyntaxErrorException() { super(); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTimeoutException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTimeoutException.java (.../MySQLTimeoutException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTimeoutException.java (.../MySQLTimeoutException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,32 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLTimeoutException extends MySQLTransientException { + static final long serialVersionUID = -789621240523230339L; + public MySQLTimeoutException(String reason, String SQLState, int vendorCode) { super(reason, SQLState, vendorCode); } @@ -40,9 +42,4 @@ public MySQLTimeoutException() { super("Statement cancelled due to timeout or client request"); } - - public int getErrorCode() { - // TODO Auto-generated method stub - return super.getErrorCode(); - } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransactionRollbackException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransactionRollbackException.java (.../MySQLTransactionRollbackException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransactionRollbackException.java (.../MySQLTransactionRollbackException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,32 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; -public class MySQLTransactionRollbackException extends MySQLTransientException { +public class MySQLTransactionRollbackException extends MySQLTransientException implements DeadlockTimeoutRollbackMarker { + static final long serialVersionUID = 6034999468737801730L; + public MySQLTransactionRollbackException(String reason, String SQLState, int vendorCode) { super(reason, SQLState, vendorCode); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransientConnectionException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransientConnectionException.java (.../MySQLTransientConnectionException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransientConnectionException.java (.../MySQLTransientConnectionException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,32 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; public class MySQLTransientConnectionException extends MySQLTransientException { + static final long serialVersionUID = 8699144578759941201L; + public MySQLTransientConnectionException(String reason, String SQLState, int vendorCode) { super(reason, SQLState, vendorCode); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransientException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransientException.java (.../MySQLTransientException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/MySQLTransientException.java (.../MySQLTransientException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,32 +1,34 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.exceptions; import java.sql.SQLException; public class MySQLTransientException extends SQLException { + static final long serialVersionUID = -1885878228558607563L; + public MySQLTransientException(String reason, String SQLState, int vendorCode) { super(reason, SQLState, vendorCode); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/CommunicationsException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/CommunicationsException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/CommunicationsException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,86 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.net.BindException; + +import java.sql.SQLRecoverableException; + +import com.mysql.jdbc.MySQLConnection; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.StreamingNotifiable; + +/** + * An exception to represent communications errors with the database. + * + * Attempts to provide 'friendler' error messages to end-users, including last + * time a packet was sent to the database, what the client-timeout is set to, + * and whether the idle time has been exceeded. + * + * @author Mark Matthews + * + * @version $Id: CommunicationsException.java,v 1.1.2.1 2005/05/13 18:58:37 + * mmatthews Exp $ + */ +public class CommunicationsException extends SQLRecoverableException implements StreamingNotifiable { + + private String exceptionMessage; + + private boolean streamingResultSetInPlay = false; + + public CommunicationsException(MySQLConnection conn, long lastPacketSentTimeMs, + long lastPacketReceivedTimeMs, + Exception underlyingException) { + + this.exceptionMessage = SQLError.createLinkFailureMessageBasedOnHeuristics(conn, + lastPacketSentTimeMs, lastPacketReceivedTimeMs, underlyingException, this.streamingResultSetInPlay); + + if (underlyingException != null) { + initCause(underlyingException); + } + } + + /* + * (non-Javadoc) + * + * @see java.lang.Throwable#getMessage() + */ + public String getMessage() { + return this.exceptionMessage; + } + + /* + * (non-Javadoc) + * + * @see java.sql.SQLException#getSQLState() + */ + public String getSQLState() { + return SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE; + } + + public void setWasStreamingResults() { + this.streamingResultSetInPlay = true; + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,45 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLDataException; + +public class MySQLDataException extends SQLDataException { + + public MySQLDataException() { + super(); + } + + public MySQLDataException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLDataException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLDataException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLIntegrityConstraintViolationException; + +public class MySQLIntegrityConstraintViolationException extends + SQLIntegrityConstraintViolationException { + + public MySQLIntegrityConstraintViolationException() { + super(); + } + + public MySQLIntegrityConstraintViolationException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLIntegrityConstraintViolationException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLIntegrityConstraintViolationException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLInvalidAuthorizationSpecException; + +public class MySQLInvalidAuthorizationSpecException extends + SQLInvalidAuthorizationSpecException { + + public MySQLInvalidAuthorizationSpecException() { + super(); + } + + public MySQLInvalidAuthorizationSpecException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLInvalidAuthorizationSpecException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLInvalidAuthorizationSpecException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLNonTransientConnectionException; + +public class MySQLNonTransientConnectionException extends + SQLNonTransientConnectionException { + + public MySQLNonTransientConnectionException() { + super(); + } + + public MySQLNonTransientConnectionException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLNonTransientConnectionException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLNonTransientConnectionException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLException; +import java.sql.SQLNonTransientException; + +public class MySQLNonTransientException extends SQLNonTransientException { + + public MySQLNonTransientException() { + super(); + } + + public MySQLNonTransientException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLNonTransientException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLNonTransientException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLQueryInterruptedException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLQueryInterruptedException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLQueryInterruptedException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,44 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +public class MySQLQueryInterruptedException extends com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientException { + + public MySQLQueryInterruptedException() { + super(); + } + + public MySQLQueryInterruptedException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLQueryInterruptedException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLQueryInterruptedException(String reason) { + super(reason); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,45 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLSyntaxErrorException; + +public class MySQLSyntaxErrorException extends SQLSyntaxErrorException { + + public MySQLSyntaxErrorException() { + super(); + } + + public MySQLSyntaxErrorException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLSyntaxErrorException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLSyntaxErrorException(String reason) { + super(reason); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,50 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLTimeoutException; + +public class MySQLTimeoutException extends SQLTimeoutException { + + public MySQLTimeoutException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLTimeoutException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLTimeoutException(String reason) { + super(reason); + } + + public MySQLTimeoutException() { + super("Statement cancelled due to timeout or client request"); + } + + public int getErrorCode() { + // TODO Auto-generated method stub + return super.getErrorCode(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,48 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLTransactionRollbackException; + +import com.mysql.jdbc.exceptions.DeadlockTimeoutRollbackMarker; + +public class MySQLTransactionRollbackException extends SQLTransactionRollbackException implements DeadlockTimeoutRollbackMarker { + + public MySQLTransactionRollbackException(String reason, String SQLState, + int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLTransactionRollbackException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLTransactionRollbackException(String reason) { + super(reason); + } + + public MySQLTransactionRollbackException() { + super(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLTransientConnectionException; + +public class MySQLTransientConnectionException extends SQLTransientConnectionException { + + public MySQLTransientConnectionException(String reason, String SQLState, + int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLTransientConnectionException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLTransientConnectionException(String reason) { + super(reason); + } + + public MySQLTransientConnectionException() { + super(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,46 @@ +/* + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.exceptions.jdbc4; + +import java.sql.SQLException; +import java.sql.SQLTransientException; + +public class MySQLTransientException extends SQLTransientException { + + public MySQLTransientException(String reason, String SQLState, int vendorCode) { + super(reason, SQLState, vendorCode); + } + + public MySQLTransientException(String reason, String SQLState) { + super(reason, SQLState); + } + + public MySQLTransientException(String reason) { + super(reason); + } + + public MySQLTransientException() { + super(); + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/c3p0/MysqlConnectionTester.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/c3p0/MysqlConnectionTester.java (.../MysqlConnectionTester.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/c3p0/MysqlConnectionTester.java (.../MysqlConnectionTester.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,25 +1,26 @@ /* - Copyright (C) 2002-2005 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ + package com.mysql.jdbc.integration.c3p0; import java.lang.reflect.Method; @@ -46,12 +47,12 @@ private static final Object[] NO_ARGS_ARRAY = new Object[0]; - private Method pingMethod; + private transient Method pingMethod; public MysqlConnectionTester() { try { pingMethod = com.mysql.jdbc.Connection.class - .getMethod("ping", null); + .getMethod("ping", (Class[])null); } catch (Exception ex) { // punt, we have no way to recover, other than we now use 'SELECT 1' // for @@ -103,7 +104,9 @@ * java.lang.Throwable) */ public int statusOnException(Connection arg0, Throwable throwable) { - if (throwable instanceof CommunicationsException) { + if (throwable instanceof CommunicationsException + || "com.mysql.jdbc.exceptions.jdbc4.CommunicationsException" + .equals(throwable.getClass().getName())) { return CONNECTION_IS_INVALID; } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/jboss/ExtendedMysqlExceptionSorter.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/jboss/ExtendedMysqlExceptionSorter.java (.../ExtendedMysqlExceptionSorter.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/jboss/ExtendedMysqlExceptionSorter.java (.../ExtendedMysqlExceptionSorter.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,30 +1,30 @@ /* - Copyright (C) 2002-2005 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ + package com.mysql.jdbc.integration.jboss; import java.sql.SQLException; -import org.jboss.resource.adapter.jdbc.ExceptionSorter; import org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter; /** @@ -36,6 +36,8 @@ */ public final class ExtendedMysqlExceptionSorter extends MySQLExceptionSorter { + static final long serialVersionUID = -2454582336945931069L; + /* * (non-Javadoc) * Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java (.../MysqlValidConnectionChecker.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java (.../MysqlValidConnectionChecker.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,37 +1,35 @@ /* - Copyright (C) 2002-2006 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ package com.mysql.jdbc.integration.jboss; import java.io.Serializable; -import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import org.jboss.resource.adapter.jdbc.ValidConnectionChecker; -import com.mysql.jdbc.SQLError; - /** * A more efficient connection checker for JBoss. * @@ -41,31 +39,9 @@ public final class MysqlValidConnectionChecker implements ValidConnectionChecker, Serializable { - private static final long serialVersionUID = 3258689922776119348L; + private static final long serialVersionUID = 8909421133577519177L; - private Method pingMethod; - - private Method pingMethodWrapped; - - private final static Object[] NO_ARGS_OBJECT_ARRAY = new Object[0]; - public MysqlValidConnectionChecker() { - try { - // Avoid classloader goofiness - Class mysqlConnection = Thread.currentThread() - .getContextClassLoader().loadClass( - "com.mysql.jdbc.Connection"); - - pingMethod = mysqlConnection.getMethod("ping", null); - - Class mysqlConnectionWrapper = Thread.currentThread() - .getContextClassLoader().loadClass( - "com.mysql.jdbc.jdbc2.optional.ConnectionWrapper"); - - pingMethodWrapped = mysqlConnectionWrapper.getMethod("ping", null); - } catch (Exception ex) { - // Punt, we'll use 'SELECT 1' to do the check - } } /* @@ -74,44 +50,17 @@ * @see org.jboss.resource.adapter.jdbc.ValidConnectionChecker#isValidConnection(java.sql.Connection) */ public SQLException isValidConnection(Connection conn) { - if (conn instanceof com.mysql.jdbc.Connection) { - if (pingMethod != null) { - try { - this.pingMethod.invoke(conn, null); - - return null; - } catch (Exception ex) { - if (ex instanceof SQLException) { - return (SQLException) ex; - } - - return SQLError.createSQLException("Ping failed: " + ex.toString()); - } - } - } else if (conn instanceof com.mysql.jdbc.jdbc2.optional.ConnectionWrapper) { - if (pingMethodWrapped != null) { - try { - this.pingMethodWrapped.invoke(conn, null); - - return null; - } catch (Exception ex) { - if (ex instanceof SQLException) { - return (SQLException) ex; - } - - return SQLError.createSQLException("Ping failed: " + ex.toString()); - } - } - } - // Punt and use 'SELECT 1' + // Use "/* ping */ SELECT 1" which will send + // pings across multi-connections too in case the connection + // was "wrapped" by Jboss in any way... Statement pingStatement = null; try { pingStatement = conn.createStatement(); - pingStatement.executeQuery("SELECT 1").close(); + pingStatement.executeQuery("/* ping */ SELECT 1").close(); return null; } catch (SQLException sqlEx) { Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/ResultSetScannerInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/ResultSetScannerInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/ResultSetScannerInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,112 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.interceptors; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.SQLException; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ResultSetInternalMethods; +import com.mysql.jdbc.Statement; +import com.mysql.jdbc.StatementInterceptor; + +public class ResultSetScannerInterceptor implements StatementInterceptor { + + protected Pattern regexP; + + public void init(Connection conn, Properties props) throws SQLException { + String regexFromUser = props.getProperty("resultSetScannerRegex"); + + if (regexFromUser == null || regexFromUser.length() == 0) { + throw new SQLException("resultSetScannerRegex must be configured, and must be > 0 characters"); + } + + try { + this.regexP = Pattern.compile(regexFromUser); + } catch (Throwable t) { + SQLException sqlEx = new SQLException("Can't use configured regex due to underlying exception."); + sqlEx.initCause(t); + + throw sqlEx; + } + + } + + public ResultSetInternalMethods postProcess(String sql, Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection) + throws SQLException { + + // requirement of anonymous class + final ResultSetInternalMethods finalResultSet = originalResultSet; + + return (ResultSetInternalMethods)Proxy.newProxyInstance(originalResultSet.getClass().getClassLoader(), + new Class[] {ResultSetInternalMethods.class}, + new InvocationHandler() { + + public Object invoke(Object proxy, Method method, + Object[] args) throws Throwable { + + Object invocationResult = method.invoke(finalResultSet, args); + + String methodName = method.getName(); + + if (invocationResult != null && invocationResult instanceof String + || "getString".equals(methodName) + || "getObject".equals(methodName) + || "getObjectStoredProc".equals(methodName)) { + Matcher matcher = regexP.matcher(invocationResult.toString()); + + if (matcher.matches()) { + throw new SQLException("value disallowed by filter"); + } + } + + return invocationResult; + }}); + + } + + public ResultSetInternalMethods preProcess(String sql, Statement interceptedStatement, + Connection connection) throws SQLException { + // we don't care about this event + + return null; + } + + // we don't issue queries, so it should be safe to intercept + // at any point + public boolean executeTopLevelOnly() { + return false; + } + + public void destroy() { + + + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/ServerStatusDiffInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/ServerStatusDiffInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/ServerStatusDiffInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,106 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.interceptors; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ResultSetInternalMethods; +import com.mysql.jdbc.Statement; +import com.mysql.jdbc.StatementInterceptor; +import com.mysql.jdbc.Util; + +public class ServerStatusDiffInterceptor implements StatementInterceptor { + + private Map preExecuteValues = new HashMap(); + + private Map postExecuteValues = new HashMap(); + + public void init(Connection conn, Properties props) throws SQLException { + + } + + public ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection) + throws SQLException { + + if (connection.versionMeetsMinimum(5, 0, 2)) { + populateMapWithSessionStatusValues(connection, this.postExecuteValues); + + connection.getLog().logInfo( + "Server status change for statement:\n" + + Util.calculateDifferences(this.preExecuteValues, + this.postExecuteValues)); + } + + return null; // we don't actually modify a result set + + } + + private void populateMapWithSessionStatusValues(Connection connection, + Map toPopulate) throws SQLException { + java.sql.Statement stmt = null; + java.sql.ResultSet rs = null; + + try { + toPopulate.clear(); + + stmt = connection.createStatement(); + rs = stmt.executeQuery("SHOW SESSION STATUS"); + Util.resultSetToMap(toPopulate, rs); + } finally { + if (rs != null) { + rs.close(); + } + + if (stmt != null) { + stmt.close(); + } + } + } + + public ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException { + + if (connection.versionMeetsMinimum(5, 0, 2)) { + populateMapWithSessionStatusValues(connection, + this.preExecuteValues); + } + + return null; // we don't actually modify a result set + } + + public boolean executeTopLevelOnly() { + return true; + } + + public void destroy() { + + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/SessionAssociationInterceptor.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/SessionAssociationInterceptor.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/interceptors/SessionAssociationInterceptor.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,91 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.interceptors; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Properties; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ResultSetInternalMethods; +import com.mysql.jdbc.Statement; +import com.mysql.jdbc.StatementInterceptor; + +public class SessionAssociationInterceptor implements StatementInterceptor { + + protected String currentSessionKey; + protected final static ThreadLocal sessionLocal = new ThreadLocal(); + + public static final void setSessionKey(String key) { + sessionLocal.set(key); + } + + public static final void resetSessionKey() { + sessionLocal.set(null); + } + + public static final String getSessionKey() { + return sessionLocal.get(); + } + + public boolean executeTopLevelOnly() { + return true; + } + + public void init(Connection conn, Properties props) throws SQLException { + + } + + public ResultSetInternalMethods postProcess(String sql, + Statement interceptedStatement, + ResultSetInternalMethods originalResultSet, Connection connection) + throws SQLException { + return null; + } + + public ResultSetInternalMethods preProcess(String sql, + Statement interceptedStatement, Connection connection) + throws SQLException { + String key = getSessionKey(); + + if (key != null && !key.equals(this.currentSessionKey)) { + PreparedStatement pstmt = connection.clientPrepareStatement("SET @mysql_proxy_session=?"); + + try { + pstmt.setString(1, key); + pstmt.execute(); + } finally { + pstmt.close(); + } + + this.currentSessionKey = key; + } + + return null; + } + + public void destroy() { + + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java (.../CallableStatementWrapper.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java (.../CallableStatementWrapper.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,39 +1,38 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - */ package com.mysql.jdbc.jdbc2.optional; import java.io.InputStream; import java.io.Reader; +import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Date; -import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.SQLException; import java.sql.Time; @@ -42,6 +41,7 @@ import java.util.Map; import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Util; /** * Wraps callable statements created by pooled connections. @@ -52,6 +52,44 @@ public class CallableStatementWrapper extends PreparedStatementWrapper implements CallableStatement { + private static final Constructor JDBC_4_CALLABLE_STATEMENT_WRAPPER_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_CALLABLE_STATEMENT_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4CallableStatementWrapper").getConstructor( + new Class[] { ConnectionWrapper.class, + MysqlPooledConnection.class, + CallableStatement.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_CALLABLE_STATEMENT_WRAPPER_CTOR = null; + } + } + + protected static CallableStatementWrapper getInstance(ConnectionWrapper c, + MysqlPooledConnection conn, + CallableStatement toWrap) throws SQLException { + if (!Util.isJdbc4()) { + return new CallableStatementWrapper(c, + conn, toWrap); + } + + return (CallableStatementWrapper) Util.handleNewInstance( + JDBC_4_CALLABLE_STATEMENT_WRAPPER_CTOR, + new Object[] {c, + conn, toWrap }, conn.getExceptionInterceptor()); + } + + + /** * @param c * @param conn @@ -76,7 +114,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -97,7 +135,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -113,11 +151,11 @@ try { if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).wasNull(); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -135,11 +173,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getString(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -156,11 +194,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBoolean(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -178,11 +216,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getByte(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -200,11 +238,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getShort(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -222,11 +260,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getInt(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -244,11 +282,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getLong(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -266,11 +304,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getFloat(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -288,11 +326,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getDouble(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -311,11 +349,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getBigDecimal( parameterIndex, scale); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -333,11 +371,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBytes(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -355,11 +393,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getDate(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -377,11 +415,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getTime(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -399,11 +437,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getTimestamp(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -421,11 +459,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getObject(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -443,11 +481,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBigDecimal(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -460,17 +498,17 @@ * * @see java.sql.CallableStatement#getObject(int, java.util.Map) */ - public Object getObject(int parameterIndex, Map typeMap) + public Object getObject(int parameterIndex, Map> typeMap) throws SQLException { try { if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getObject( parameterIndex, typeMap); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -487,11 +525,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getRef(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -509,11 +547,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBlob(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -531,11 +569,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getClob(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -552,11 +590,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getArray(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -573,11 +611,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getDate( parameterIndex, cal); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -594,11 +632,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getTime( parameterIndex, cal); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -616,11 +654,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getTimestamp( parameterIndex, cal); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -642,7 +680,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -664,7 +702,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -686,7 +724,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -708,7 +746,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -725,11 +763,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getURL(parameterIndex); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -750,7 +788,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -770,7 +808,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -790,7 +828,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -810,7 +848,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -830,7 +868,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -849,7 +887,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -869,7 +907,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -889,7 +927,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -909,7 +947,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -931,7 +969,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -952,7 +990,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -972,7 +1010,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -992,7 +1030,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1012,7 +1050,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1034,7 +1072,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1056,7 +1094,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1079,7 +1117,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1101,7 +1139,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1123,7 +1161,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1144,7 +1182,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1166,7 +1204,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1188,7 +1226,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1210,7 +1248,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1232,7 +1270,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1254,7 +1292,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -1271,11 +1309,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getString(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1292,11 +1330,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBoolean(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1314,11 +1352,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getByte(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1336,11 +1374,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getShort(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1358,11 +1396,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getInt(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1380,11 +1418,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getLong(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1402,11 +1440,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getFloat(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1424,11 +1462,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getDouble(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1446,11 +1484,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBytes(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1468,11 +1506,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getDate(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1490,11 +1528,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getTime(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1512,11 +1550,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getTimestamp(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1534,11 +1572,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getObject(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1556,11 +1594,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBigDecimal(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1573,17 +1611,17 @@ * * @see java.sql.CallableStatement#getObject(int, java.util.Map) */ - public Object getObject(String parameterName, Map typeMap) + public Object getObject(String parameterName, Map> typeMap) throws SQLException { try { if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getObject( parameterName, typeMap); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1600,11 +1638,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getRef(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1622,11 +1660,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getBlob(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1644,11 +1682,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getClob(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1665,11 +1703,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getArray(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1686,11 +1724,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getDate( parameterName, cal); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1707,11 +1745,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getTime( parameterName, cal); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1729,11 +1767,11 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt).getTimestamp( parameterName, cal); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -1750,16 +1788,850 @@ if (this.wrappedStmt != null) { return ((CallableStatement) this.wrappedStmt) .getURL(parameterName); - } else { - throw SQLError.createSQLException( - "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); } + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } return null; } +// +// public Reader getCharacterStream(int parameterIndex) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getCharacterStream(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public Reader getCharacterStream(String parameterName) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getCharacterStream(parameterName); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public Reader getNCharacterStream(int parameterIndex) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getCharacterStream(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public Reader getNCharacterStream(String parameterName) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getNCharacterStream(parameterName); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public NClob getNClob(int parameterIndex) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getNClob(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public NClob getNClob(String parameterName) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getNClob(parameterName); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public String getNString(int parameterIndex) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getNString(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public String getNString(String parameterName) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getNString(parameterName); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public RowId getRowId(int parameterIndex) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getRowId(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public RowId getRowId(String parameterName) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getRowId(parameterName); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public SQLXML getSQLXML(int parameterIndex) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getSQLXML(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public SQLXML getSQLXML(String parameterName) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .getSQLXML(parameterName); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return null; +// } +// +// public void setAsciiStream(String parameterName, InputStream x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setAsciiStream(parameterName, x) ; +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setAsciiStream(parameterName, x, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBinaryStream(String parameterName, InputStream x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBinaryStream(parameterName, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBinaryStream(parameterName, x, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(String parameterName, Blob x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBlob(parameterName, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(String parameterName, InputStream inputStream) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBlob(parameterName, inputStream); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBlob(parameterName, inputStream, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setCharacterStream(String parameterName, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setCharacterStream(parameterName, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setCharacterStream(parameterName, reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(String parameterName, Clob x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setClob(parameterName, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(String parameterName, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setClob(parameterName, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(String parameterName, Reader reader, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setClob(parameterName, reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNCharacterStream(String parameterName, Reader value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNCharacterStream(parameterName, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNCharacterStream(parameterName, value, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(String parameterName, NClob value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNClob(parameterName, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(String parameterName, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNClob(parameterName, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(String parameterName, Reader reader, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNClob(parameterName, reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNString(String parameterName, String value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNString(parameterName, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setRowId(String parameterName, RowId x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setRowId(parameterName, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setSQLXML(parameterName, xmlObject); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setAsciiStream(parameterIndex, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setAsciiStream(parameterIndex, x, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBinaryStream(parameterIndex, x) ; +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBinaryStream(parameterIndex, x, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBlob(parameterIndex, inputStream); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setBlob(parameterIndex, inputStream, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setCharacterStream(parameterIndex, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .getCharacterStream(parameterIndex); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(int parameterIndex, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setClob(parameterIndex, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setClob(parameterIndex, reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNCharacterStream(parameterIndex, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// } +// +// public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNCharacterStream(parameterIndex, value, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(int parameterIndex, NClob value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNClob(parameterIndex, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(int parameterIndex, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNClob(parameterIndex, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNClob(parameterIndex, reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNString(int parameterIndex, String value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setNString(parameterIndex, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setRowId(int parameterIndex, RowId x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setRowId(parameterIndex, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setSQLXML(parameterIndex, xmlObject); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// } +// +// public boolean isClosed() throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// .isClosed(); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return true; +// } +// +// public boolean isPoolable() throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((CallableStatement) this.wrappedStmt) +// . isPoolable(); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return false; +// } +// +// public void setPoolable(boolean poolable) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((CallableStatement) this.wrappedStmt) +// .setPoolable(poolable); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// } +// +// public boolean isWrapperFor(Class arg0) throws SQLException { +// throw SQLError.notImplemented(); +// } +// +// public Object unwrap(Class arg0) throws SQLException { +// throw SQLError.notImplemented(); +// } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java (.../ConnectionWrapper.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java (.../ConnectionWrapper.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,36 +1,45 @@ /* - Copyright (C) 2002-2006 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; -import java.sql.Connection; +import java.lang.reflect.Constructor; import java.sql.SQLException; import java.sql.Savepoint; import java.sql.Statement; +import java.util.Map; +import java.util.Properties; +import java.util.TimeZone; +import java.util.concurrent.Executor; +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ExceptionInterceptor; +import com.mysql.jdbc.Extension; +import com.mysql.jdbc.MySQLConnection; import com.mysql.jdbc.MysqlErrorNumbers; import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Util; +import com.mysql.jdbc.log.Log; /** * This class serves as a wrapper for the org.gjt.mm.mysql.jdbc2.Connection @@ -55,15 +64,50 @@ * @see org.gjt.mm.mysql.jdbc2.optional.MysqlPooledConnection */ public class ConnectionWrapper extends WrapperBase implements Connection { - private com.mysql.jdbc.Connection mc = null; + protected Connection mc = null; - private MysqlPooledConnection mpc = null; - private String invalidHandleStr = "Logical handle no longer valid"; private boolean closed; + private boolean isForXa; - + + private static final Constructor JDBC_4_CONNECTION_WRAPPER_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_CONNECTION_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper") + .getConstructor( + new Class[] { MysqlPooledConnection.class, + Connection.class, Boolean.TYPE }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_CONNECTION_WRAPPER_CTOR = null; + } + } + + protected static ConnectionWrapper getInstance( + MysqlPooledConnection mysqlPooledConnection, + Connection mysqlConnection, boolean forXa) throws SQLException { + if (!Util.isJdbc4()) { + return new ConnectionWrapper(mysqlPooledConnection, + mysqlConnection, forXa); + } + + return (ConnectionWrapper) Util.handleNewInstance( + JDBC_4_CONNECTION_WRAPPER_CTOR, new Object[] { + mysqlPooledConnection, mysqlConnection, + Boolean.valueOf(forXa) }, mysqlPooledConnection.getExceptionInterceptor()); + } + /** * Construct a new LogicalHandle and set instance variables * @@ -76,14 +120,13 @@ * if an error occurs. */ public ConnectionWrapper(MysqlPooledConnection mysqlPooledConnection, - com.mysql.jdbc.Connection mysqlConnection, - boolean forXa) throws SQLException { - this.mpc = mysqlPooledConnection; + Connection mysqlConnection, boolean forXa) throws SQLException { + super(mysqlPooledConnection); + this.mc = mysqlConnection; this.closed = false; - this.pooledConnection = this.mpc; this.isForXa = forXa; - + if (this.isForXa) { setInGlobalTx(false); } @@ -99,11 +142,12 @@ checkClosed(); if (autoCommit && isInGlobalTx()) { - throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", - SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, - MysqlErrorNumbers.ER_XA_RMERR); + throw SQLError.createSQLException( + "Can't set autocommit to 'true' on an XAConnection", + SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, + MysqlErrorNumbers.ER_XA_RMERR, this.exceptionInterceptor); } - + try { this.mc.setAutoCommit(autoCommit); } catch (SQLException sqlException) { @@ -176,7 +220,7 @@ return (this.closed || this.mc.isClosed()); } - public boolean isMasterConnection() throws SQLException { + public boolean isMasterConnection() { return this.mc.isMasterConnection(); } @@ -206,7 +250,7 @@ } return Statement.CLOSE_CURRENT_RESULT; // we don't reach this code, - // compiler can't tell + // compiler can't tell } /** @@ -280,11 +324,12 @@ checkClosed(); if (isInGlobalTx()) { - throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", - SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, - MysqlErrorNumbers.ER_XA_RMERR); + throw SQLError.createSQLException( + "Can't set autocommit to 'true' on an XAConnection", + SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, + MysqlErrorNumbers.ER_XA_RMERR, this.exceptionInterceptor); } - + try { return this.mc.setSavepoint(); } catch (SQLException sqlException) { @@ -301,11 +346,12 @@ checkClosed(); if (isInGlobalTx()) { - throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", - SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, - MysqlErrorNumbers.ER_XA_RMERR); + throw SQLError.createSQLException( + "Can't set autocommit to 'true' on an XAConnection", + SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, + MysqlErrorNumbers.ER_XA_RMERR, this.exceptionInterceptor); } - + try { return this.mc.setSavepoint(arg0); } catch (SQLException sqlException) { @@ -347,32 +393,17 @@ } return TRANSACTION_REPEATABLE_READ; // we don't reach this code, - // compiler can't tell + // compiler can't tell } - /** - * Passes call to method on physical connection instance. Notifies listeners - * of any caught exceptions before re-throwing to client. - * - * @see java.sql.Connection#setTypeMap() - */ - public void setTypeMap(java.util.Map map) throws SQLException { - checkClosed(); - try { - this.mc.setTypeMap(map); - } catch (SQLException sqlException) { - checkAndFireConnectionError(sqlException); - } - } - /** * Passes call to method on physical connection instance. Notifies listeners * of any caught exceptions before re-throwing to client. * * @see java.sql.Connection#getTypeMap() */ - public java.util.Map getTypeMap() throws SQLException { + public java.util.Map> getTypeMap() throws SQLException { checkClosed(); try { @@ -442,12 +473,13 @@ */ public void commit() throws SQLException { checkClosed(); - + if (isInGlobalTx()) { - throw SQLError.createSQLException( - "Can't call commit() on an XAConnection associated with a global transaction", - SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, - MysqlErrorNumbers.ER_XA_RMERR); + throw SQLError + .createSQLException( + "Can't call commit() on an XAConnection associated with a global transaction", + SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, + MysqlErrorNumbers.ER_XA_RMERR, this.exceptionInterceptor); } try { @@ -467,7 +499,7 @@ checkClosed(); try { - return new StatementWrapper(this, this.mpc, this.mc + return StatementWrapper.getInstance(this, this.pooledConnection, this.mc .createStatement()); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -487,7 +519,7 @@ checkClosed(); try { - return new StatementWrapper(this, this.mpc, this.mc + return StatementWrapper.getInstance(this, this.pooledConnection, this.mc .createStatement(resultSetType, resultSetConcurrency)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -504,7 +536,7 @@ checkClosed(); try { - return new StatementWrapper(this, this.mpc, this.mc + return StatementWrapper.getInstance(this, this.pooledConnection, this.mc .createStatement(arg0, arg1, arg2)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -542,7 +574,7 @@ checkClosed(); try { - return new CallableStatementWrapper(this, this.mpc, this.mc + return CallableStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareCall(sql)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -562,7 +594,7 @@ checkClosed(); try { - return new CallableStatementWrapper(this, this.mpc, this.mc + return CallableStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareCall(sql, resultSetType, resultSetConcurrency)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -579,7 +611,7 @@ checkClosed(); try { - return new CallableStatementWrapper(this, this.mpc, this.mc + return CallableStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareCall(arg0, arg1, arg2, arg3)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -588,36 +620,35 @@ return null; // we don't reach this code, compiler can't tell } - public java.sql.PreparedStatement clientPrepare(String sql) throws SQLException - { + public java.sql.PreparedStatement clientPrepare(String sql) + throws SQLException { checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, - this.mc.clientPrepareStatement(sql)); + return new PreparedStatementWrapper(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); } - + return null; } - + public java.sql.PreparedStatement clientPrepare(String sql, - int resultSetType, int resultSetConcurrency) throws SQLException - { + int resultSetType, int resultSetConcurrency) throws SQLException { checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, - this.mc.clientPrepareStatement(sql, - resultSetType, resultSetConcurrency)); + return new PreparedStatementWrapper(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql, resultSetType, + resultSetConcurrency)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); } - + return null; } - + /** * Passes call to method on physical connection instance. Notifies listeners * of any caught exceptions before re-throwing to client. @@ -629,7 +660,7 @@ checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, this.mc + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareStatement(sql)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -649,8 +680,9 @@ checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, this.mc - .prepareStatement(sql, resultSetType, resultSetConcurrency)); + return PreparedStatementWrapper + .getInstance(this, this.pooledConnection, this.mc.prepareStatement(sql, + resultSetType, resultSetConcurrency)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); } @@ -666,7 +698,7 @@ checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, this.mc + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareStatement(arg0, arg1, arg2, arg3)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -683,7 +715,7 @@ checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, this.mc + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareStatement(arg0, arg1)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -700,7 +732,7 @@ checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, this.mc + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareStatement(arg0, arg1)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -717,7 +749,7 @@ checkClosed(); try { - return new PreparedStatementWrapper(this, this.mpc, this.mc + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc .prepareStatement(arg0, arg1)); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); @@ -748,13 +780,14 @@ public void rollback() throws SQLException { checkClosed(); - if (isInGlobalTx()) { - throw SQLError.createSQLException("Can't call rollback() on an XAConnection associated with a global transaction", - SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, - MysqlErrorNumbers.ER_XA_RMERR); + throw SQLError + .createSQLException( + "Can't call rollback() on an XAConnection associated with a global transaction", + SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, + MysqlErrorNumbers.ER_XA_RMERR, this.exceptionInterceptor); } - + try { this.mc.rollback(); } catch (SQLException sqlException) { @@ -769,42 +802,40 @@ checkClosed(); if (isInGlobalTx()) { - throw SQLError.createSQLException("Can't call rollback() on an XAConnection associated with a global transaction", - SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, - MysqlErrorNumbers.ER_XA_RMERR); + throw SQLError + .createSQLException( + "Can't call rollback() on an XAConnection associated with a global transaction", + SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, + MysqlErrorNumbers.ER_XA_RMERR, this.exceptionInterceptor); } - + try { this.mc.rollback(arg0); } catch (SQLException sqlException) { checkAndFireConnectionError(sqlException); } } - public boolean isSameResource(Connection c) { + public boolean isSameResource(com.mysql.jdbc.Connection c) { if (c instanceof ConnectionWrapper) { - return this.mc.isSameResource(((ConnectionWrapper)c).mc); - } else if (c instanceof com.mysql.jdbc.Connection) { - return this.mc.isSameResource((com.mysql.jdbc.Connection)c); + return this.mc.isSameResource(((ConnectionWrapper) c).mc); } - - return false; + return this.mc.isSameResource(c); } - + protected void close(boolean fireClosedEvent) throws SQLException { - synchronized (this.mpc) { + synchronized (this.pooledConnection) { if (this.closed) { return; } - if (!isInGlobalTx() - && this.mc.getRollbackOnPooledClose() + if (!isInGlobalTx() && this.mc.getRollbackOnPooledClose() && !this.getAutoCommit()) { rollback(); } if (fireClosedEvent) { - this.mpc.callListener( + this.pooledConnection.callConnectionEventListeners( MysqlPooledConnection.CONNECTION_CLOSED_EVENT, null); } @@ -817,23 +848,2048 @@ } } - private void checkClosed() throws SQLException { + public void checkClosed() throws SQLException { if (this.closed) { - throw SQLError.createSQLException(this.invalidHandleStr); + throw SQLError.createSQLException(this.invalidHandleStr, this.exceptionInterceptor); } } - protected boolean isInGlobalTx() { + public boolean isInGlobalTx() { return this.mc.isInGlobalTx(); } - protected void setInGlobalTx(boolean flag) { + public void setInGlobalTx(boolean flag) { this.mc.setInGlobalTx(flag); } - + public void ping() throws SQLException { if (this.mc != null) { this.mc.ping(); } } -} + + public void changeUser(String userName, String newPassword) + throws SQLException { + checkClosed(); + + try { + this.mc.changeUser(userName, newPassword); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + } + + public void clearHasTriedMaster() { + this.mc.clearHasTriedMaster(); + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql) + throws SQLException { + checkClosed(); + + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql, autoGenKeyIndex)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql, resultSetType, + resultSetConcurrency)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql, resultSetType, + resultSetConcurrency, resultSetHoldability)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql, autoGenKeyIndexes)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement clientPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .clientPrepareStatement(sql, autoGenKeyColNames)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public int getActiveStatementCount() { + return this.mc.getActiveStatementCount(); + } + + public Log getLog() throws SQLException { + return this.mc.getLog(); + } + + public String getServerCharacterEncoding() { + return this.mc.getServerCharacterEncoding(); + } + + public TimeZone getServerTimezoneTZ() { + return this.mc.getServerTimezoneTZ(); + } + + public String getStatementComment() { + return this.mc.getStatementComment(); + } + + public boolean hasTriedMaster() { + return this.mc.hasTriedMaster(); + } + + public boolean isAbonormallyLongQuery(long millisOrNanos) { + return this.mc.isAbonormallyLongQuery(millisOrNanos); + } + + public boolean isNoBackslashEscapesSet() { + return this.mc.isNoBackslashEscapesSet(); + } + + public boolean lowerCaseTableNames() { + return this.mc.lowerCaseTableNames(); + } + + public boolean parserKnowsUnicode() { + return this.mc.parserKnowsUnicode(); + } + + public void reportQueryTime(long millisOrNanos) { + this.mc.reportQueryTime(millisOrNanos); + } + + public void resetServerState() throws SQLException { + checkClosed(); + + try { + this.mc.resetServerState(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql) + throws SQLException { + checkClosed(); + + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .serverPrepareStatement(sql)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int autoGenKeyIndex) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .serverPrepareStatement(sql, autoGenKeyIndex)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .serverPrepareStatement(sql, resultSetType, + resultSetConcurrency)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .serverPrepareStatement(sql, resultSetType, + resultSetConcurrency, resultSetHoldability)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + int[] autoGenKeyIndexes) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .serverPrepareStatement(sql, autoGenKeyIndexes)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public java.sql.PreparedStatement serverPrepareStatement(String sql, + String[] autoGenKeyColNames) throws SQLException { + try { + return PreparedStatementWrapper.getInstance(this, this.pooledConnection, this.mc + .serverPrepareStatement(sql, autoGenKeyColNames)); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public void setFailedOver(boolean flag) { + this.mc.setFailedOver(flag); + + } + + public void setPreferSlaveDuringFailover(boolean flag) { + this.mc.setPreferSlaveDuringFailover(flag); + } + + public void setStatementComment(String comment) { + this.mc.setStatementComment(comment); + + } + + public void shutdownServer() throws SQLException { + checkClosed(); + + try { + this.mc.shutdownServer(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + } + + public boolean supportsIsolationLevel() { + return this.mc.supportsIsolationLevel(); + } + + public boolean supportsQuotedIdentifiers() { + return this.mc.supportsQuotedIdentifiers(); + } + + public boolean supportsTransactions() { + return this.mc.supportsTransactions(); + } + + public boolean versionMeetsMinimum(int major, int minor, int subminor) + throws SQLException { + checkClosed(); + + try { + return this.mc.versionMeetsMinimum(major, minor, subminor); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return false; + } + + public String exposeAsXml() throws SQLException { + checkClosed(); + + try { + return this.mc.exposeAsXml(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; + } + + public boolean getAllowLoadLocalInfile() { + return this.mc.getAllowLoadLocalInfile(); + } + + public boolean getAllowMultiQueries() { + return this.mc.getAllowMultiQueries(); + } + + public boolean getAllowNanAndInf() { + return this.mc.getAllowNanAndInf(); + } + + public boolean getAllowUrlInLocalInfile() { + return this.mc.getAllowUrlInLocalInfile(); + } + + public boolean getAlwaysSendSetIsolation() { + return this.mc.getAlwaysSendSetIsolation(); + } + + public boolean getAutoClosePStmtStreams() { + return this.mc.getAutoClosePStmtStreams(); + } + + public boolean getAutoDeserialize() { + return this.mc.getAutoDeserialize(); + } + + public boolean getAutoGenerateTestcaseScript() { + return this.mc.getAutoGenerateTestcaseScript(); + } + + public boolean getAutoReconnectForPools() { + return this.mc.getAutoReconnectForPools(); + } + + public boolean getAutoSlowLog() { + return this.mc.getAutoSlowLog(); + } + + public int getBlobSendChunkSize() { + return this.mc.getBlobSendChunkSize(); + } + + public boolean getBlobsAreStrings() { + return this.mc.getBlobsAreStrings(); + } + + public boolean getCacheCallableStatements() { + return this.mc.getCacheCallableStatements(); + } + + public boolean getCacheCallableStmts() { + return this.mc.getCacheCallableStmts(); + } + + public boolean getCachePrepStmts() { + return this.mc.getCachePrepStmts(); + } + + public boolean getCachePreparedStatements() { + return this.mc.getCachePreparedStatements(); + } + + public boolean getCacheResultSetMetadata() { + return this.mc.getCacheResultSetMetadata(); + } + + public boolean getCacheServerConfiguration() { + return this.mc.getCacheServerConfiguration(); + } + + public int getCallableStatementCacheSize() { + return this.mc.getCallableStatementCacheSize(); + } + + public int getCallableStmtCacheSize() { + return this.mc.getCallableStmtCacheSize(); + } + + public boolean getCapitalizeTypeNames() { + return this.mc.getCapitalizeTypeNames(); + } + + public String getCharacterSetResults() { + return this.mc.getCharacterSetResults(); + } + + public String getClientCertificateKeyStorePassword() { + return this.mc.getClientCertificateKeyStorePassword(); + } + + public String getClientCertificateKeyStoreType() { + return this.mc.getClientCertificateKeyStoreType(); + } + + public String getClientCertificateKeyStoreUrl() { + return this.mc.getClientCertificateKeyStoreUrl(); + } + + public String getClientInfoProvider() { + return this.mc.getClientInfoProvider(); + } + + public String getClobCharacterEncoding() { + return this.mc.getClobCharacterEncoding(); + } + + public boolean getClobberStreamingResults() { + return this.mc.getClobberStreamingResults(); + } + + public int getConnectTimeout() { + return this.mc.getConnectTimeout(); + } + + public String getConnectionCollation() { + return this.mc.getConnectionCollation(); + } + + public String getConnectionLifecycleInterceptors() { + return this.mc.getConnectionLifecycleInterceptors(); + } + + public boolean getContinueBatchOnError() { + return this.mc.getContinueBatchOnError(); + } + + public boolean getCreateDatabaseIfNotExist() { + return this.mc.getCreateDatabaseIfNotExist(); + } + + public int getDefaultFetchSize() { + return this.mc.getDefaultFetchSize(); + } + + public boolean getDontTrackOpenResources() { + return this.mc.getDontTrackOpenResources(); + } + + public boolean getDumpMetadataOnColumnNotFound() { + return this.mc.getDumpMetadataOnColumnNotFound(); + } + + public boolean getDumpQueriesOnException() { + return this.mc.getDumpQueriesOnException(); + } + + public boolean getDynamicCalendars() { + return this.mc.getDynamicCalendars(); + } + + public boolean getElideSetAutoCommits() { + return this.mc.getElideSetAutoCommits(); + } + + public boolean getEmptyStringsConvertToZero() { + return this.mc.getEmptyStringsConvertToZero(); + } + + public boolean getEmulateLocators() { + return this.mc.getEmulateLocators(); + } + + public boolean getEmulateUnsupportedPstmts() { + return this.mc.getEmulateUnsupportedPstmts(); + } + + public boolean getEnablePacketDebug() { + return this.mc.getEnablePacketDebug(); + } + + public boolean getEnableQueryTimeouts() { + return this.mc.getEnableQueryTimeouts(); + } + + public String getEncoding() { + return this.mc.getEncoding(); + } + + public boolean getExplainSlowQueries() { + return this.mc.getExplainSlowQueries(); + } + + public boolean getFailOverReadOnly() { + return this.mc.getFailOverReadOnly(); + } + + public boolean getFunctionsNeverReturnBlobs() { + return this.mc.getFunctionsNeverReturnBlobs(); + } + + public boolean getGatherPerfMetrics() { + return this.mc.getGatherPerfMetrics(); + } + + public boolean getGatherPerformanceMetrics() { + return this.mc.getGatherPerformanceMetrics(); + } + + public boolean getGenerateSimpleParameterMetadata() { + return this.mc.getGenerateSimpleParameterMetadata(); + } + + public boolean getHoldResultsOpenOverStatementClose() { + return this.mc.getHoldResultsOpenOverStatementClose(); + } + + public boolean getIgnoreNonTxTables() { + return this.mc.getIgnoreNonTxTables(); + } + + public boolean getIncludeInnodbStatusInDeadlockExceptions() { + return this.mc.getIncludeInnodbStatusInDeadlockExceptions(); + } + + public int getInitialTimeout() { + return this.mc.getInitialTimeout(); + } + + public boolean getInteractiveClient() { + return this.mc.getInteractiveClient(); + } + + public boolean getIsInteractiveClient() { + return this.mc.getIsInteractiveClient(); + } + + public boolean getJdbcCompliantTruncation() { + return this.mc.getJdbcCompliantTruncation(); + } + + public boolean getJdbcCompliantTruncationForReads() { + return this.mc.getJdbcCompliantTruncationForReads(); + } + + public String getLargeRowSizeThreshold() { + return this.mc.getLargeRowSizeThreshold(); + } + + public String getLoadBalanceStrategy() { + return this.mc.getLoadBalanceStrategy(); + } + + public String getLocalSocketAddress() { + return this.mc.getLocalSocketAddress(); + } + + public int getLocatorFetchBufferSize() { + return this.mc.getLocatorFetchBufferSize(); + } + + public boolean getLogSlowQueries() { + return this.mc.getLogSlowQueries(); + } + + public boolean getLogXaCommands() { + return this.mc.getLogXaCommands(); + } + + public String getLogger() { + return this.mc.getLogger(); + } + + public String getLoggerClassName() { + return this.mc.getLoggerClassName(); + } + + public boolean getMaintainTimeStats() { + return this.mc.getMaintainTimeStats(); + } + + public int getMaxQuerySizeToLog() { + return this.mc.getMaxQuerySizeToLog(); + } + + public int getMaxReconnects() { + return this.mc.getMaxReconnects(); + } + + public int getMaxRows() { + return this.mc.getMaxRows(); + } + + public int getMetadataCacheSize() { + return this.mc.getMetadataCacheSize(); + } + + public int getNetTimeoutForStreamingResults() { + return this.mc.getNetTimeoutForStreamingResults(); + } + + public boolean getNoAccessToProcedureBodies() { + return this.mc.getNoAccessToProcedureBodies(); + } + + public boolean getNoDatetimeStringSync() { + return this.mc.getNoDatetimeStringSync(); + } + + public boolean getNoTimezoneConversionForTimeType() { + return this.mc.getNoTimezoneConversionForTimeType(); + } + + public boolean getNullCatalogMeansCurrent() { + return this.mc.getNullCatalogMeansCurrent(); + } + + public boolean getNullNamePatternMatchesAll() { + return this.mc.getNullNamePatternMatchesAll(); + } + + public boolean getOverrideSupportsIntegrityEnhancementFacility() { + return this.mc.getOverrideSupportsIntegrityEnhancementFacility(); + } + + public int getPacketDebugBufferSize() { + return this.mc.getPacketDebugBufferSize(); + } + + public boolean getPadCharsWithSpace() { + return this.mc.getPadCharsWithSpace(); + } + + public boolean getParanoid() { + return this.mc.getParanoid(); + } + + public boolean getPedantic() { + return this.mc.getPedantic(); + } + + public boolean getPinGlobalTxToPhysicalConnection() { + return this.mc.getPinGlobalTxToPhysicalConnection(); + } + + public boolean getPopulateInsertRowWithDefaultValues() { + return this.mc.getPopulateInsertRowWithDefaultValues(); + } + + public int getPrepStmtCacheSize() { + return this.mc.getPrepStmtCacheSize(); + } + + public int getPrepStmtCacheSqlLimit() { + return this.mc.getPrepStmtCacheSqlLimit(); + } + + public int getPreparedStatementCacheSize() { + return this.mc.getPreparedStatementCacheSize(); + } + + public int getPreparedStatementCacheSqlLimit() { + return this.mc.getPreparedStatementCacheSqlLimit(); + } + + public boolean getProcessEscapeCodesForPrepStmts() { + return this.mc.getProcessEscapeCodesForPrepStmts(); + } + + public boolean getProfileSQL() { + return this.mc.getProfileSQL(); + } + + public boolean getProfileSql() { + return this.mc.getProfileSql(); + } + + public String getPropertiesTransform() { + return this.mc.getPropertiesTransform(); + } + + public int getQueriesBeforeRetryMaster() { + return this.mc.getQueriesBeforeRetryMaster(); + } + + public boolean getReconnectAtTxEnd() { + return this.mc.getReconnectAtTxEnd(); + } + + public boolean getRelaxAutoCommit() { + return this.mc.getRelaxAutoCommit(); + } + + public int getReportMetricsIntervalMillis() { + return this.mc.getReportMetricsIntervalMillis(); + } + + public boolean getRequireSSL() { + return this.mc.getRequireSSL(); + } + + public String getResourceId() { + return this.mc.getResourceId(); + } + + public int getResultSetSizeThreshold() { + return this.mc.getResultSetSizeThreshold(); + } + + public boolean getRewriteBatchedStatements() { + return this.mc.getRewriteBatchedStatements(); + } + + public boolean getRollbackOnPooledClose() { + return this.mc.getRollbackOnPooledClose(); + } + + public boolean getRoundRobinLoadBalance() { + return this.mc.getRoundRobinLoadBalance(); + } + + public boolean getRunningCTS13() { + return this.mc.getRunningCTS13(); + } + + public int getSecondsBeforeRetryMaster() { + return this.mc.getSecondsBeforeRetryMaster(); + } + + public String getServerTimezone() { + return this.mc.getServerTimezone(); + } + + public String getSessionVariables() { + return this.mc.getSessionVariables(); + } + + public int getSlowQueryThresholdMillis() { + return this.mc.getSlowQueryThresholdMillis(); + } + + public long getSlowQueryThresholdNanos() { + return this.mc.getSlowQueryThresholdNanos(); + } + + public String getSocketFactory() { + return this.mc.getSocketFactory(); + } + + public String getSocketFactoryClassName() { + return this.mc.getSocketFactoryClassName(); + } + + public int getSocketTimeout() { + return this.mc.getSocketTimeout(); + } + + public String getStatementInterceptors() { + return this.mc.getStatementInterceptors(); + } + + public boolean getStrictFloatingPoint() { + return this.mc.getStrictFloatingPoint(); + } + + public boolean getStrictUpdates() { + return this.mc.getStrictUpdates(); + } + + public boolean getTcpKeepAlive() { + return this.mc.getTcpKeepAlive(); + } + + public boolean getTcpNoDelay() { + return this.mc.getTcpNoDelay(); + } + + public int getTcpRcvBuf() { + return this.mc.getTcpRcvBuf(); + } + + public int getTcpSndBuf() { + return this.mc.getTcpSndBuf(); + } + + public int getTcpTrafficClass() { + return this.mc.getTcpTrafficClass(); + } + + public boolean getTinyInt1isBit() { + return this.mc.getTinyInt1isBit(); + } + + public boolean getTraceProtocol() { + return this.mc.getTraceProtocol(); + } + + public boolean getTransformedBitIsBoolean() { + return this.mc.getTransformedBitIsBoolean(); + } + + public boolean getTreatUtilDateAsTimestamp() { + return this.mc.getTreatUtilDateAsTimestamp(); + } + + public String getTrustCertificateKeyStorePassword() { + return this.mc.getTrustCertificateKeyStorePassword(); + } + + public String getTrustCertificateKeyStoreType() { + return this.mc.getTrustCertificateKeyStoreType(); + } + + public String getTrustCertificateKeyStoreUrl() { + return this.mc.getTrustCertificateKeyStoreUrl(); + } + + public boolean getUltraDevHack() { + return this.mc.getUltraDevHack(); + } + + public boolean getUseBlobToStoreUTF8OutsideBMP() { + return this.mc.getUseBlobToStoreUTF8OutsideBMP(); + } + + public boolean getUseCompression() { + return this.mc.getUseCompression(); + } + + public String getUseConfigs() { + return this.mc.getUseConfigs(); + } + + public boolean getUseCursorFetch() { + return this.mc.getUseCursorFetch(); + } + + public boolean getUseDirectRowUnpack() { + return this.mc.getUseDirectRowUnpack(); + } + + public boolean getUseDynamicCharsetInfo() { + return this.mc.getUseDynamicCharsetInfo(); + } + + public boolean getUseFastDateParsing() { + return this.mc.getUseFastDateParsing(); + } + + public boolean getUseFastIntParsing() { + return this.mc.getUseFastIntParsing(); + } + + public boolean getUseGmtMillisForDatetimes() { + return this.mc.getUseGmtMillisForDatetimes(); + } + + public boolean getUseHostsInPrivileges() { + return this.mc.getUseHostsInPrivileges(); + } + + public boolean getUseInformationSchema() { + return this.mc.getUseInformationSchema(); + } + + public boolean getUseJDBCCompliantTimezoneShift() { + return this.mc.getUseJDBCCompliantTimezoneShift(); + } + + public boolean getUseJvmCharsetConverters() { + return this.mc.getUseJvmCharsetConverters(); + } + + public boolean getUseLocalSessionState() { + return this.mc.getUseLocalSessionState(); + } + + public boolean getUseNanosForElapsedTime() { + return this.mc.getUseNanosForElapsedTime(); + } + + public boolean getUseOldAliasMetadataBehavior() { + return this.mc.getUseOldAliasMetadataBehavior(); + } + + public boolean getUseOldUTF8Behavior() { + return this.mc.getUseOldUTF8Behavior(); + } + + public boolean getUseOnlyServerErrorMessages() { + return this.mc.getUseOnlyServerErrorMessages(); + } + + public boolean getUseReadAheadInput() { + return this.mc.getUseReadAheadInput(); + } + + public boolean getUseSSL() { + return this.mc.getUseSSL(); + } + + public boolean getUseSSPSCompatibleTimezoneShift() { + return this.mc.getUseSSPSCompatibleTimezoneShift(); + } + + public boolean getUseServerPrepStmts() { + return this.mc.getUseServerPrepStmts(); + } + + public boolean getUseServerPreparedStmts() { + return this.mc.getUseServerPreparedStmts(); + } + + public boolean getUseSqlStateCodes() { + return this.mc.getUseSqlStateCodes(); + } + + public boolean getUseStreamLengthsInPrepStmts() { + return this.mc.getUseStreamLengthsInPrepStmts(); + } + + public boolean getUseTimezone() { + return this.mc.getUseTimezone(); + } + + public boolean getUseUltraDevWorkAround() { + return this.mc.getUseUltraDevWorkAround(); + } + + public boolean getUseUnbufferedInput() { + return this.mc.getUseUnbufferedInput(); + } + + public boolean getUseUnicode() { + return this.mc.getUseUnicode(); + } + + public boolean getUseUsageAdvisor() { + return this.mc.getUseUsageAdvisor(); + } + + public String getUtf8OutsideBmpExcludedColumnNamePattern() { + return this.mc.getUtf8OutsideBmpExcludedColumnNamePattern(); + } + + public String getUtf8OutsideBmpIncludedColumnNamePattern() { + return this.mc.getUtf8OutsideBmpIncludedColumnNamePattern(); + } + + public boolean getYearIsDateType() { + return this.mc.getYearIsDateType(); + } + + public String getZeroDateTimeBehavior() { + return this.mc.getZeroDateTimeBehavior(); + } + + public void setAllowLoadLocalInfile(boolean property) { + this.mc.setAllowLoadLocalInfile(property); + } + + public void setAllowMultiQueries(boolean property) { + this.mc.setAllowMultiQueries(property); + } + + public void setAllowNanAndInf(boolean flag) { + this.mc.setAllowNanAndInf(flag); + } + + public void setAllowUrlInLocalInfile(boolean flag) { + this.mc.setAllowUrlInLocalInfile(flag); + } + + public void setAlwaysSendSetIsolation(boolean flag) { + this.mc.setAlwaysSendSetIsolation(flag); + } + + public void setAutoClosePStmtStreams(boolean flag) { + this.mc.setAutoClosePStmtStreams(flag); + } + + public void setAutoDeserialize(boolean flag) { + this.mc.setAutoDeserialize(flag); + } + + public void setAutoGenerateTestcaseScript(boolean flag) { + this.mc.setAutoGenerateTestcaseScript(flag); + } + + public void setAutoReconnect(boolean flag) { + this.mc.setAutoReconnect(flag); + } + + public void setAutoReconnectForConnectionPools(boolean property) { + this.mc.setAutoReconnectForConnectionPools(property); + } + + public void setAutoReconnectForPools(boolean flag) { + this.mc.setAutoReconnectForPools(flag); + } + + public void setAutoSlowLog(boolean flag) { + this.mc.setAutoSlowLog(flag); + } + + public void setBlobSendChunkSize(String value) throws SQLException { + this.mc.setBlobSendChunkSize(value); + } + + public void setBlobsAreStrings(boolean flag) { + this.mc.setBlobsAreStrings(flag); + } + + public void setCacheCallableStatements(boolean flag) { + this.mc.setCacheCallableStatements(flag); + } + + public void setCacheCallableStmts(boolean flag) { + this.mc.setCacheCallableStmts(flag); + } + + public void setCachePrepStmts(boolean flag) { + this.mc.setCachePrepStmts(flag); + } + + public void setCachePreparedStatements(boolean flag) { + this.mc.setCachePreparedStatements(flag); + } + + public void setCacheResultSetMetadata(boolean property) { + this.mc.setCacheResultSetMetadata(property); + } + + public void setCacheServerConfiguration(boolean flag) { + this.mc.setCacheServerConfiguration(flag); + } + + public void setCallableStatementCacheSize(int size) throws SQLException { + this.mc.setCallableStatementCacheSize(size); + } + + public void setCallableStmtCacheSize(int cacheSize) throws SQLException { + this.mc.setCallableStmtCacheSize(cacheSize); + } + + public void setCapitalizeDBMDTypes(boolean property) { + this.mc.setCapitalizeDBMDTypes(property); + } + + public void setCapitalizeTypeNames(boolean flag) { + this.mc.setCapitalizeTypeNames(flag); + } + + public void setCharacterEncoding(String encoding) { + this.mc.setCharacterEncoding(encoding); + } + + public void setCharacterSetResults(String characterSet) { + this.mc.setCharacterSetResults(characterSet); + } + + public void setClientCertificateKeyStorePassword(String value) { + this.mc.setClientCertificateKeyStorePassword(value); + } + + public void setClientCertificateKeyStoreType(String value) { + this.mc.setClientCertificateKeyStoreType(value); + } + + public void setClientCertificateKeyStoreUrl(String value) { + this.mc.setClientCertificateKeyStoreUrl(value); + } + + public void setClientInfoProvider(String classname) { + this.mc.setClientInfoProvider(classname); + } + + public void setClobCharacterEncoding(String encoding) { + this.mc.setClobCharacterEncoding(encoding); + } + + public void setClobberStreamingResults(boolean flag) { + this.mc.setClobberStreamingResults(flag); + } + + public void setConnectTimeout(int timeoutMs) throws SQLException { + this.mc.setConnectTimeout(timeoutMs); + } + + public void setConnectionCollation(String collation) { + this.mc.setConnectionCollation(collation); + } + + public void setConnectionLifecycleInterceptors(String interceptors) { + this.mc.setConnectionLifecycleInterceptors(interceptors); + } + + public void setContinueBatchOnError(boolean property) { + this.mc.setContinueBatchOnError(property); + } + + public void setCreateDatabaseIfNotExist(boolean flag) { + this.mc.setCreateDatabaseIfNotExist(flag); + } + + public void setDefaultFetchSize(int n) throws SQLException { + this.mc.setDefaultFetchSize(n); + } + + public void setDetectServerPreparedStmts(boolean property) { + this.mc.setDetectServerPreparedStmts(property); + } + + public void setDontTrackOpenResources(boolean flag) { + this.mc.setDontTrackOpenResources(flag); + } + + public void setDumpMetadataOnColumnNotFound(boolean flag) { + this.mc.setDumpMetadataOnColumnNotFound(flag); + } + + public void setDumpQueriesOnException(boolean flag) { + this.mc.setDumpQueriesOnException(flag); + } + + public void setDynamicCalendars(boolean flag) { + this.mc.setDynamicCalendars(flag); + } + + public void setElideSetAutoCommits(boolean flag) { + this.mc.setElideSetAutoCommits(flag); + } + + public void setEmptyStringsConvertToZero(boolean flag) { + this.mc.setEmptyStringsConvertToZero(flag); + } + + public void setEmulateLocators(boolean property) { + this.mc.setEmulateLocators(property); + } + + public void setEmulateUnsupportedPstmts(boolean flag) { + this.mc.setEmulateUnsupportedPstmts(flag); + } + + public void setEnablePacketDebug(boolean flag) { + this.mc.setEnablePacketDebug(flag); + } + + public void setEnableQueryTimeouts(boolean flag) { + this.mc.setEnableQueryTimeouts(flag); + } + + public void setEncoding(String property) { + this.mc.setEncoding(property); + } + + public void setExplainSlowQueries(boolean flag) { + this.mc.setExplainSlowQueries(flag); + } + + public void setFailOverReadOnly(boolean flag) { + this.mc.setFailOverReadOnly(flag); + } + + public void setFunctionsNeverReturnBlobs(boolean flag) { + this.mc.setFunctionsNeverReturnBlobs(flag); + } + + public void setGatherPerfMetrics(boolean flag) { + this.mc.setGatherPerfMetrics(flag); + } + + public void setGatherPerformanceMetrics(boolean flag) { + this.mc.setGatherPerformanceMetrics(flag); + } + + public void setGenerateSimpleParameterMetadata(boolean flag) { + this.mc.setGenerateSimpleParameterMetadata(flag); + } + + public void setHoldResultsOpenOverStatementClose(boolean flag) { + this.mc.setHoldResultsOpenOverStatementClose(flag); + } + + public void setIgnoreNonTxTables(boolean property) { + this.mc.setIgnoreNonTxTables(property); + } + + public void setIncludeInnodbStatusInDeadlockExceptions(boolean flag) { + this.mc.setIncludeInnodbStatusInDeadlockExceptions(flag); + } + + public void setInitialTimeout(int property) throws SQLException { + this.mc.setInitialTimeout(property); + } + + public void setInteractiveClient(boolean property) { + this.mc.setInteractiveClient(property); + } + + public void setIsInteractiveClient(boolean property) { + this.mc.setIsInteractiveClient(property); + } + + public void setJdbcCompliantTruncation(boolean flag) { + this.mc.setJdbcCompliantTruncation(flag); + } + + public void setJdbcCompliantTruncationForReads( + boolean jdbcCompliantTruncationForReads) { + this.mc + .setJdbcCompliantTruncationForReads(jdbcCompliantTruncationForReads); + } + + public void setLargeRowSizeThreshold(String value) throws SQLException { + this.mc.setLargeRowSizeThreshold(value); + } + + public void setLoadBalanceStrategy(String strategy) { + this.mc.setLoadBalanceStrategy(strategy); + } + + public void setLocalSocketAddress(String address) { + this.mc.setLocalSocketAddress(address); + } + + public void setLocatorFetchBufferSize(String value) throws SQLException { + this.mc.setLocatorFetchBufferSize(value); + } + + public void setLogSlowQueries(boolean flag) { + this.mc.setLogSlowQueries(flag); + } + + public void setLogXaCommands(boolean flag) { + this.mc.setLogXaCommands(flag); + } + + public void setLogger(String property) { + this.mc.setLogger(property); + } + + public void setLoggerClassName(String className) { + this.mc.setLoggerClassName(className); + } + + public void setMaintainTimeStats(boolean flag) { + this.mc.setMaintainTimeStats(flag); + } + + public void setMaxQuerySizeToLog(int sizeInBytes) throws SQLException { + this.mc.setMaxQuerySizeToLog(sizeInBytes); + } + + public void setMaxReconnects(int property) throws SQLException { + this.mc.setMaxReconnects(property); + } + + public void setMaxRows(int property) throws SQLException { + this.mc.setMaxRows(property); + } + + public void setMetadataCacheSize(int value) throws SQLException { + this.mc.setMetadataCacheSize(value); + } + + public void setNetTimeoutForStreamingResults(int value) throws SQLException { + this.mc.setNetTimeoutForStreamingResults(value); + } + + public void setNoAccessToProcedureBodies(boolean flag) { + this.mc.setNoAccessToProcedureBodies(flag); + } + + public void setNoDatetimeStringSync(boolean flag) { + this.mc.setNoDatetimeStringSync(flag); + } + + public void setNoTimezoneConversionForTimeType(boolean flag) { + this.mc.setNoTimezoneConversionForTimeType(flag); + } + + public void setNullCatalogMeansCurrent(boolean value) { + this.mc.setNullCatalogMeansCurrent(value); + } + + public void setNullNamePatternMatchesAll(boolean value) { + this.mc.setNullNamePatternMatchesAll(value); + } + + public void setOverrideSupportsIntegrityEnhancementFacility(boolean flag) { + this.mc.setOverrideSupportsIntegrityEnhancementFacility(flag); + } + + public void setPacketDebugBufferSize(int size) throws SQLException { + this.mc.setPacketDebugBufferSize(size); + } + + public void setPadCharsWithSpace(boolean flag) { + this.mc.setPadCharsWithSpace(flag); + } + + public void setParanoid(boolean property) { + this.mc.setParanoid(property); + } + + public void setPedantic(boolean property) { + this.mc.setPedantic(property); + } + + public void setPinGlobalTxToPhysicalConnection(boolean flag) { + this.mc.setPinGlobalTxToPhysicalConnection(flag); + } + + public void setPopulateInsertRowWithDefaultValues(boolean flag) { + this.mc.setPopulateInsertRowWithDefaultValues(flag); + } + + public void setPrepStmtCacheSize(int cacheSize) throws SQLException { + this.mc.setPrepStmtCacheSize(cacheSize); + } + + public void setPrepStmtCacheSqlLimit(int sqlLimit) throws SQLException { + this.mc.setPrepStmtCacheSqlLimit(sqlLimit); + } + + public void setPreparedStatementCacheSize(int cacheSize) throws SQLException { + this.mc.setPreparedStatementCacheSize(cacheSize); + } + + public void setPreparedStatementCacheSqlLimit(int cacheSqlLimit) throws SQLException { + this.mc.setPreparedStatementCacheSqlLimit(cacheSqlLimit); + } + + public void setProcessEscapeCodesForPrepStmts(boolean flag) { + this.mc.setProcessEscapeCodesForPrepStmts(flag); + } + + public void setProfileSQL(boolean flag) { + this.mc.setProfileSQL(flag); + } + + public void setProfileSql(boolean property) { + this.mc.setProfileSql(property); + } + + public void setPropertiesTransform(String value) { + this.mc.setPropertiesTransform(value); + } + + public void setQueriesBeforeRetryMaster(int property) throws SQLException { + this.mc.setQueriesBeforeRetryMaster(property); + } + + public void setReconnectAtTxEnd(boolean property) { + this.mc.setReconnectAtTxEnd(property); + } + + public void setRelaxAutoCommit(boolean property) { + this.mc.setRelaxAutoCommit(property); + } + + public void setReportMetricsIntervalMillis(int millis) throws SQLException { + this.mc.setReportMetricsIntervalMillis(millis); + } + + public void setRequireSSL(boolean property) { + this.mc.setRequireSSL(property); + } + + public void setResourceId(String resourceId) { + this.mc.setResourceId(resourceId); + } + + public void setResultSetSizeThreshold(int threshold) throws SQLException { + this.mc.setResultSetSizeThreshold(threshold); + } + + public void setRetainStatementAfterResultSetClose(boolean flag) { + this.mc.setRetainStatementAfterResultSetClose(flag); + } + + public void setRewriteBatchedStatements(boolean flag) { + this.mc.setRewriteBatchedStatements(flag); + } + + public void setRollbackOnPooledClose(boolean flag) { + this.mc.setRollbackOnPooledClose(flag); + } + + public void setRoundRobinLoadBalance(boolean flag) { + this.mc.setRoundRobinLoadBalance(flag); + } + + public void setRunningCTS13(boolean flag) { + this.mc.setRunningCTS13(flag); + } + + public void setSecondsBeforeRetryMaster(int property) throws SQLException { + this.mc.setSecondsBeforeRetryMaster(property); + } + + public void setServerTimezone(String property) { + this.mc.setServerTimezone(property); + } + + public void setSessionVariables(String variables) { + this.mc.setSessionVariables(variables); + } + + public void setSlowQueryThresholdMillis(int millis) throws SQLException { + this.mc.setSlowQueryThresholdMillis(millis); + } + + public void setSlowQueryThresholdNanos(long nanos) throws SQLException { + this.mc.setSlowQueryThresholdNanos(nanos); + } + + public void setSocketFactory(String name) { + this.mc.setSocketFactory(name); + } + + public void setSocketFactoryClassName(String property) { + this.mc.setSocketFactoryClassName(property); + } + + public void setSocketTimeout(int property) throws SQLException { + this.mc.setSocketTimeout(property); + } + + public void setStatementInterceptors(String value) { + this.mc.setStatementInterceptors(value); + } + + public void setStrictFloatingPoint(boolean property) { + this.mc.setStrictFloatingPoint(property); + } + + public void setStrictUpdates(boolean property) { + this.mc.setStrictUpdates(property); + } + + public void setTcpKeepAlive(boolean flag) { + this.mc.setTcpKeepAlive(flag); + } + + public void setTcpNoDelay(boolean flag) { + this.mc.setTcpNoDelay(flag); + } + + public void setTcpRcvBuf(int bufSize) throws SQLException { + this.mc.setTcpRcvBuf(bufSize); + } + + public void setTcpSndBuf(int bufSize) throws SQLException { + this.mc.setTcpSndBuf(bufSize); + } + + public void setTcpTrafficClass(int classFlags) throws SQLException { + this.mc.setTcpTrafficClass(classFlags); + } + + public void setTinyInt1isBit(boolean flag) { + this.mc.setTinyInt1isBit(flag); + } + + public void setTraceProtocol(boolean flag) { + this.mc.setTraceProtocol(flag); + } + + public void setTransformedBitIsBoolean(boolean flag) { + this.mc.setTransformedBitIsBoolean(flag); + } + + public void setTreatUtilDateAsTimestamp(boolean flag) { + this.mc.setTreatUtilDateAsTimestamp(flag); + } + + public void setTrustCertificateKeyStorePassword(String value) { + this.mc.setTrustCertificateKeyStorePassword(value); + } + + public void setTrustCertificateKeyStoreType(String value) { + this.mc.setTrustCertificateKeyStoreType(value); + } + + public void setTrustCertificateKeyStoreUrl(String value) { + this.mc.setTrustCertificateKeyStoreUrl(value); + } + + public void setUltraDevHack(boolean flag) { + this.mc.setUltraDevHack(flag); + } + + public void setUseBlobToStoreUTF8OutsideBMP(boolean flag) { + this.mc.setUseBlobToStoreUTF8OutsideBMP(flag); + } + + public void setUseCompression(boolean property) { + this.mc.setUseCompression(property); + } + + public void setUseConfigs(String configs) { + this.mc.setUseConfigs(configs); + } + + public void setUseCursorFetch(boolean flag) { + this.mc.setUseCursorFetch(flag); + } + + public void setUseDirectRowUnpack(boolean flag) { + this.mc.setUseDirectRowUnpack(flag); + } + + public void setUseDynamicCharsetInfo(boolean flag) { + this.mc.setUseDynamicCharsetInfo(flag); + } + + public void setUseFastDateParsing(boolean flag) { + this.mc.setUseFastDateParsing(flag); + } + + public void setUseFastIntParsing(boolean flag) { + this.mc.setUseFastIntParsing(flag); + } + + public void setUseGmtMillisForDatetimes(boolean flag) { + this.mc.setUseGmtMillisForDatetimes(flag); + } + + public void setUseHostsInPrivileges(boolean property) { + this.mc.setUseHostsInPrivileges(property); + } + + public void setUseInformationSchema(boolean flag) { + this.mc.setUseInformationSchema(flag); + } + + public void setUseJDBCCompliantTimezoneShift(boolean flag) { + this.mc.setUseJDBCCompliantTimezoneShift(flag); + } + + public void setUseJvmCharsetConverters(boolean flag) { + this.mc.setUseJvmCharsetConverters(flag); + } + + public void setUseLocalSessionState(boolean flag) { + this.mc.setUseLocalSessionState(flag); + } + + public void setUseNanosForElapsedTime(boolean flag) { + this.mc.setUseNanosForElapsedTime(flag); + } + + public void setUseOldAliasMetadataBehavior(boolean flag) { + this.mc.setUseOldAliasMetadataBehavior(flag); + } + + public void setUseOldUTF8Behavior(boolean flag) { + this.mc.setUseOldUTF8Behavior(flag); + } + + public void setUseOnlyServerErrorMessages(boolean flag) { + this.mc.setUseOnlyServerErrorMessages(flag); + } + + public void setUseReadAheadInput(boolean flag) { + this.mc.setUseReadAheadInput(flag); + } + + public void setUseSSL(boolean property) { + this.mc.setUseSSL(property); + } + + public void setUseSSPSCompatibleTimezoneShift(boolean flag) { + this.mc.setUseSSPSCompatibleTimezoneShift(flag); + } + + public void setUseServerPrepStmts(boolean flag) { + this.mc.setUseServerPrepStmts(flag); + } + + public void setUseServerPreparedStmts(boolean flag) { + this.mc.setUseServerPreparedStmts(flag); + } + + public void setUseSqlStateCodes(boolean flag) { + this.mc.setUseSqlStateCodes(flag); + } + + public void setUseStreamLengthsInPrepStmts(boolean property) { + this.mc.setUseStreamLengthsInPrepStmts(property); + } + + public void setUseTimezone(boolean property) { + this.mc.setUseTimezone(property); + } + + public void setUseUltraDevWorkAround(boolean property) { + this.mc.setUseUltraDevWorkAround(property); + } + + public void setUseUnbufferedInput(boolean flag) { + this.mc.setUseUnbufferedInput(flag); + } + + public void setUseUnicode(boolean flag) { + this.mc.setUseUnicode(flag); + } + + public void setUseUsageAdvisor(boolean useUsageAdvisorFlag) { + this.mc.setUseUsageAdvisor(useUsageAdvisorFlag); + } + + public void setUtf8OutsideBmpExcludedColumnNamePattern(String regexPattern) { + this.mc.setUtf8OutsideBmpExcludedColumnNamePattern(regexPattern); + } + + public void setUtf8OutsideBmpIncludedColumnNamePattern(String regexPattern) { + this.mc.setUtf8OutsideBmpIncludedColumnNamePattern(regexPattern); + } + + public void setYearIsDateType(boolean flag) { + this.mc.setYearIsDateType(flag); + } + + public void setZeroDateTimeBehavior(String behavior) { + this.mc.setZeroDateTimeBehavior(behavior); + } + + public boolean useUnbufferedInput() { + return this.mc.useUnbufferedInput(); + } + + public void initializeExtension(Extension ex) throws SQLException { + this.mc.initializeExtension(ex); + } + + public String getProfilerEventHandler() { + return this.mc.getProfilerEventHandler(); + } + + public void setProfilerEventHandler(String handler) { + this.mc.setProfilerEventHandler(handler); + } + + public boolean getVerifyServerCertificate() { + return this.mc.getVerifyServerCertificate(); + } + + public void setVerifyServerCertificate(boolean flag) { + this.mc.setVerifyServerCertificate(flag); + } + + public boolean getUseLegacyDatetimeCode() { + return this.mc.getUseLegacyDatetimeCode(); + } + + public void setUseLegacyDatetimeCode(boolean flag) { + this.mc.setUseLegacyDatetimeCode(flag); + } + + public int getSelfDestructOnPingMaxOperations() { + return this.mc.getSelfDestructOnPingMaxOperations(); + } + + public int getSelfDestructOnPingSecondsLifetime() { + return this.mc.getSelfDestructOnPingSecondsLifetime(); + } + + public void setSelfDestructOnPingMaxOperations(int maxOperations) throws SQLException { + this.mc.setSelfDestructOnPingMaxOperations(maxOperations); + } + + public void setSelfDestructOnPingSecondsLifetime(int seconds) throws SQLException { + this.mc.setSelfDestructOnPingSecondsLifetime(seconds); + } + + public boolean getUseColumnNamesInFindColumn() { + return this.mc.getUseColumnNamesInFindColumn(); + } + + public void setUseColumnNamesInFindColumn(boolean flag) { + this.mc.setUseColumnNamesInFindColumn(flag); + } + + public boolean getUseLocalTransactionState() { + return this.mc.getUseLocalTransactionState(); + } + + public void setUseLocalTransactionState(boolean flag) { + this.mc.setUseLocalTransactionState(flag); + } + + public boolean getCompensateOnDuplicateKeyUpdateCounts() { + return this.mc.getCompensateOnDuplicateKeyUpdateCounts(); + } + + public void setCompensateOnDuplicateKeyUpdateCounts(boolean flag) { + this.mc.setCompensateOnDuplicateKeyUpdateCounts(flag); + } + + public boolean getUseAffectedRows() { + return this.mc.getUseAffectedRows(); + } + + public void setUseAffectedRows(boolean flag) { + this.mc.setUseAffectedRows(flag); + } + + public String getPasswordCharacterEncoding() { + return this.mc.getPasswordCharacterEncoding(); + } + + public void setPasswordCharacterEncoding(String characterSet) { + this.mc.setPasswordCharacterEncoding(characterSet); + } + + public int getAutoIncrementIncrement() { + return this.mc.getAutoIncrementIncrement(); + } + + public int getLoadBalanceBlacklistTimeout() { + return this.mc.getLoadBalanceBlacklistTimeout(); + } + + public void setLoadBalanceBlacklistTimeout(int loadBalanceBlacklistTimeout) throws SQLException { + this.mc.setLoadBalanceBlacklistTimeout(loadBalanceBlacklistTimeout); + } + public int getLoadBalancePingTimeout() { + return this.mc.getLoadBalancePingTimeout(); + } + + public void setLoadBalancePingTimeout(int loadBalancePingTimeout) throws SQLException { + this.mc.setLoadBalancePingTimeout(loadBalancePingTimeout); + } + + public boolean getLoadBalanceValidateConnectionOnSwapServer() { + return this.mc.getLoadBalanceValidateConnectionOnSwapServer(); + } + + public void setLoadBalanceValidateConnectionOnSwapServer( + boolean loadBalanceValidateConnectionOnSwapServer) { + this.mc.setLoadBalanceValidateConnectionOnSwapServer(loadBalanceValidateConnectionOnSwapServer); + } + + public void setRetriesAllDown(int retriesAllDown) throws SQLException { + this.mc.setRetriesAllDown(retriesAllDown); + } + + public int getRetriesAllDown() { + return this.mc.getRetriesAllDown(); + } + + public ExceptionInterceptor getExceptionInterceptor() { + return this.pooledConnection.getExceptionInterceptor(); + } + + public String getExceptionInterceptors() { + return this.mc.getExceptionInterceptors(); + } + + public void setExceptionInterceptors(String exceptionInterceptors) { + this.mc.setExceptionInterceptors(exceptionInterceptors); + } + + public boolean getQueryTimeoutKillsConnection() { + return this.mc.getQueryTimeoutKillsConnection(); + } + + public void setQueryTimeoutKillsConnection( + boolean queryTimeoutKillsConnection) { + this.mc.setQueryTimeoutKillsConnection(queryTimeoutKillsConnection); + } + + public boolean hasSameProperties(Connection c) { + return this.mc.hasSameProperties(c); + } + + public Properties getProperties() { + return this.mc.getProperties(); + } + + public String getHost() { + return this.mc.getHost(); + } + + public void setProxy(MySQLConnection conn) { + this.mc.setProxy(conn); + } + + public boolean getRetainStatementAfterResultSetClose() { + return this.mc.getRetainStatementAfterResultSetClose(); + } + + public int getMaxAllowedPacket() { + return this.mc.getMaxAllowedPacket(); + } + + public String getLoadBalanceConnectionGroup() { + return this.mc.getLoadBalanceConnectionGroup(); + } + + public boolean getLoadBalanceEnableJMX() { + return this.mc.getLoadBalanceEnableJMX(); + } + + public String getLoadBalanceExceptionChecker() { + return this.mc + .getLoadBalanceExceptionChecker(); + } + + public String getLoadBalanceSQLExceptionSubclassFailover() { + return this.mc + .getLoadBalanceSQLExceptionSubclassFailover(); + } + + public String getLoadBalanceSQLStateFailover() { + return this.mc + .getLoadBalanceSQLStateFailover(); + } + + public void setLoadBalanceConnectionGroup(String loadBalanceConnectionGroup) { + this.mc + .setLoadBalanceConnectionGroup(loadBalanceConnectionGroup); + + } + + public void setLoadBalanceEnableJMX(boolean loadBalanceEnableJMX) { + this.mc + .setLoadBalanceEnableJMX(loadBalanceEnableJMX); + + } + + public void setLoadBalanceExceptionChecker( + String loadBalanceExceptionChecker) { + this.mc + .setLoadBalanceExceptionChecker(loadBalanceExceptionChecker); + + } + + public void setLoadBalanceSQLExceptionSubclassFailover( + String loadBalanceSQLExceptionSubclassFailover) { + this.mc + .setLoadBalanceSQLExceptionSubclassFailover(loadBalanceSQLExceptionSubclassFailover); + + } + + public void setLoadBalanceSQLStateFailover( + String loadBalanceSQLStateFailover) { + this.mc + .setLoadBalanceSQLStateFailover(loadBalanceSQLStateFailover); + + } + + + public String getLoadBalanceAutoCommitStatementRegex() { + return this.mc.getLoadBalanceAutoCommitStatementRegex(); + } + + public int getLoadBalanceAutoCommitStatementThreshold() { + return this.mc.getLoadBalanceAutoCommitStatementThreshold(); + } + + public void setLoadBalanceAutoCommitStatementRegex( + String loadBalanceAutoCommitStatementRegex) { + this.mc.setLoadBalanceAutoCommitStatementRegex(loadBalanceAutoCommitStatementRegex); + + } + + public void setLoadBalanceAutoCommitStatementThreshold( + int loadBalanceAutoCommitStatementThreshold) throws SQLException { + this.mc.setLoadBalanceAutoCommitStatementThreshold(loadBalanceAutoCommitStatementThreshold); + + } + + public void setTypeMap(Map> map) throws SQLException { + checkClosed(); + + try { + this.mc.setTypeMap(map); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + } + + public boolean getIncludeThreadDumpInDeadlockExceptions() { + return this.mc.getIncludeThreadDumpInDeadlockExceptions(); + } + + public void setIncludeThreadDumpInDeadlockExceptions(boolean flag) { + this.mc.setIncludeThreadDumpInDeadlockExceptions(flag); + + } + + public boolean getIncludeThreadNamesAsStatementComment() { + return this.mc.getIncludeThreadNamesAsStatementComment(); + } + + public void setIncludeThreadNamesAsStatementComment(boolean flag) { + this.mc.setIncludeThreadNamesAsStatementComment(flag); + } + + public boolean isServerLocal() throws SQLException { + return this.mc.isServerLocal(); + } + + public void setAuthenticationPlugins(String authenticationPlugins) { + this.mc.setAuthenticationPlugins(authenticationPlugins); + } + + public String getAuthenticationPlugins() { + return this.mc.getAuthenticationPlugins(); + } + + public void setDisabledAuthenticationPlugins( + String disabledAuthenticationPlugins) { + this.mc.setDisabledAuthenticationPlugins(disabledAuthenticationPlugins); + } + + public String getDisabledAuthenticationPlugins() { + return this.mc.getDisabledAuthenticationPlugins(); + } + + public void setDefaultAuthenticationPlugin( + String defaultAuthenticationPlugin) { + this.mc.setDefaultAuthenticationPlugin(defaultAuthenticationPlugin); + + } + + public String getDefaultAuthenticationPlugin() { + return this.mc.getDefaultAuthenticationPlugin(); + } + + public void setParseInfoCacheFactory(String factoryClassname) { + this.mc.setParseInfoCacheFactory(factoryClassname); + } + + public String getParseInfoCacheFactory() { + return this.mc.getParseInfoCacheFactory(); + } + + public void setSchema(String schema) throws SQLException { + this.mc.setSchema(schema); + } + + public String getSchema() throws SQLException { + return this.mc.getSchema(); + } + + public void abort(Executor executor) throws SQLException { + this.mc.abort(executor); + } + + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException { + this.mc.setNetworkTimeout(executor, milliseconds); + } + + public int getNetworkTimeout() throws SQLException { + return this.mc.getNetworkTimeout(); + } + + public void setServerConfigCacheFactory(String factoryClassname) { + this.mc.setServerConfigCacheFactory(factoryClassname); + } + + public String getServerConfigCacheFactory() { + return this.mc.getServerConfigCacheFactory(); + } + + public void setDisconnectOnExpiredPasswords(boolean disconnectOnExpiredPasswords) { + this.mc.setDisconnectOnExpiredPasswords(disconnectOnExpiredPasswords); + } + + public boolean getDisconnectOnExpiredPasswords() { + return this.mc.getDisconnectOnExpiredPasswords(); + } + + public void setGetProceduresReturnsFunctions(boolean getProcedureReturnsFunctions) { + this.mc.setGetProceduresReturnsFunctions(getProcedureReturnsFunctions); + } + + public boolean getGetProceduresReturnsFunctions() { + return this.mc.getGetProceduresReturnsFunctions(); + } + + public void abortInternal() throws SQLException { + this.mc.abortInternal(); + } + + public Object getConnectionMutex() { + return this.mc.getConnectionMutex(); + } + + public boolean getAllowMasterDownConnections() { + return this.mc.getAllowMasterDownConnections(); + } + + public void setAllowMasterDownConnections(boolean connectIfMasterDown) { + this.mc.setAllowMasterDownConnections(connectIfMasterDown); + } + + public boolean getReplicationEnableJMX() { + return this.mc.getReplicationEnableJMX(); + } + + public void setReplicationEnableJMX(boolean replicationEnableJMX) { + this.mc.setReplicationEnableJMX(replicationEnableJMX); + + } + + public String getConnectionAttributes() throws SQLException { + return this.mc.getConnectionAttributes(); + } + + public void setDetectCustomCollations(boolean detectCustomCollations) { + this.mc.setDetectCustomCollations(detectCustomCollations); + } + + public boolean getDetectCustomCollations() { + return this.mc.getDetectCustomCollations(); + } + + public int getSessionMaxRows() { + return this.mc.getSessionMaxRows(); + } + + public void setSessionMaxRows(int max) throws SQLException { + this.mc.setSessionMaxRows(max); + } + + public String getServerRSAPublicKeyFile() { + return this.mc.getServerRSAPublicKeyFile(); + } + + public void setServerRSAPublicKeyFile(String serverRSAPublicKeyFile) throws SQLException { + this.mc.setServerRSAPublicKeyFile(serverRSAPublicKeyFile); + } + + public boolean getAllowPublicKeyRetrieval() { + return this.mc.getAllowPublicKeyRetrieval(); + } + + public void setAllowPublicKeyRetrieval(boolean allowPublicKeyRetrieval) throws SQLException { + this.mc.setAllowPublicKeyRetrieval(allowPublicKeyRetrieval); + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4CallableStatementWrapper.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4CallableStatementWrapper.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4CallableStatementWrapper.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,1007 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.io.InputStream; +import java.io.Reader; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.RowId; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Statement; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.SQLError; + +import com.mysql.jdbc.jdbc2.optional.ConnectionWrapper; +import com.mysql.jdbc.jdbc2.optional.MysqlPooledConnection; + +/** + */ +public class JDBC4CallableStatementWrapper extends CallableStatementWrapper { + + public JDBC4CallableStatementWrapper(ConnectionWrapper c, MysqlPooledConnection conn, + CallableStatement toWrap) { + super(c, conn, toWrap); + } + + public void close() throws SQLException { + try { + super.close(); + } finally { + this.unwrappedInterfaces = null; + } + } + + public boolean isClosed() throws SQLException { + try { + if (this.wrappedStmt != null) { + return this.wrappedStmt.isClosed(); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return false; // never get here - compiler can't tell + } + + public void setPoolable(boolean poolable) throws SQLException { + try { + if (this.wrappedStmt != null) { + this.wrappedStmt.setPoolable(poolable); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public boolean isPoolable() throws SQLException { + try { + if (this.wrappedStmt != null) { + return this.wrappedStmt.isPoolable(); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return false; // never get here - compiler can't tell + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setRowId(parameterIndex, + x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, + value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setSQLXML(parameterIndex, + xmlObject); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + + public void setNString(int parameterIndex, + String value) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNString(parameterIndex, + value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNCharacterStream(int parameterIndex, + Reader value, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNCharacterStream(parameterIndex, + value, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setClob(int parameterIndex, + Reader reader, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex, + reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBlob(int parameterIndex, + InputStream inputStream, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex, + inputStream, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(int parameterIndex, + Reader reader, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, + reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setAsciiStream(int parameterIndex, + InputStream x, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setAsciiStream(parameterIndex, + x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBinaryStream(int parameterIndex, + InputStream x, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBinaryStream(parameterIndex, + x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setCharacterStream(int parameterIndex, + Reader reader, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setCharacterStream(parameterIndex, + reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setAsciiStream(int parameterIndex, + InputStream x) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setAsciiStream(parameterIndex, + x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBinaryStream(int parameterIndex, + InputStream x) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBinaryStream(parameterIndex, + x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setCharacterStream(int parameterIndex, + Reader reader) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setCharacterStream(parameterIndex, + reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + } + + public void setNCharacterStream(int parameterIndex, + Reader value) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNCharacterStream(parameterIndex, + value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + } + + public void setClob(int parameterIndex, + Reader reader) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex, + reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + } + + public void setBlob(int parameterIndex, + InputStream inputStream) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex, + inputStream); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(int parameterIndex, + Reader reader) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, + reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + /** + * Returns true if this either implements the interface argument or is + * directly or indirectly a wrapper for an object that does. Returns false + * otherwise. If this implements the interface then return true, else if + * this is a wrapper then return the result of recursively calling + * isWrapperFor on the wrapped object. If this does not + * implement the interface and is not a wrapper, return false. This method + * should be implemented as a low-cost operation compared to + * unwrap so that callers can use this method to avoid + * expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument + * should succeed. + * + * @param interfaces + * a Class defining an interface. + * @return true if this implements the interface or directly or indirectly + * wraps an object that does. + * @throws java.sql.SQLException + * if an error occurs while determining whether this is a + * wrapper for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + + boolean isInstance = iface.isInstance(this); + + if (isInstance) { + return true; + } + + String interfaceClassName = iface.getName(); + + return (interfaceClassName.equals("com.mysql.jdbc.Statement") + || interfaceClassName.equals("java.sql.Statement") + || interfaceClassName.equals("java.sql.PreparedStatement") + || interfaceClassName.equals("java.sql.Wrapper")); + } + + /** + * Returns an object that implements the given interface to allow access to + * non-standard methods, or standard methods not exposed by the proxy. The + * result may be either the object found to implement the interface or a + * proxy for that object. If the receiver implements the interface then that + * is the object. If the receiver is a wrapper and the wrapped object + * implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped + * object. If the receiver is not a wrapper and does not implement the + * interface, then an SQLException is thrown. + * + * @param iface + * A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the + * actual implementing object. + * @throws java.sql.SQLException + * If no object found that implements the interface + * @since 1.6 + */ + public synchronized T unwrap(java.lang.Class iface) + throws java.sql.SQLException { + try { + if ("java.sql.Statement".equals(iface.getName()) + || "java.sql.PreparedStatement".equals(iface.getName()) + || "java.sql.Wrapper.class".equals(iface.getName())) { + return iface.cast(this); + } + + if (unwrappedInterfaces == null) { + unwrappedInterfaces = new HashMap(); + } + + Object cachedUnwrapped = unwrappedInterfaces.get(iface); + + if (cachedUnwrapped == null) { + if (cachedUnwrapped == null) { + cachedUnwrapped = Proxy.newProxyInstance( + this.wrappedStmt.getClass().getClassLoader(), + new Class[] { iface }, + new ConnectionErrorFiringInvocationHandler(this.wrappedStmt)); + unwrappedInterfaces.put(iface, cachedUnwrapped); + } + unwrappedInterfaces.put(iface, cachedUnwrapped); + } + + return iface.cast(cachedUnwrapped); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } + + public void setRowId(String parameterName, RowId x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setRowId(parameterName, x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setSQLXML(parameterName, xmlObject); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getSQLXML(parameterIndex); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + + } + + public SQLXML getSQLXML(String parameterName) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getSQLXML(parameterName); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + public RowId getRowId(String parameterName) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getRowId(parameterName); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + public void setNClob(String parameterName, NClob value) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setNClob(parameterName, value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(String parameterName, Reader reader) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setNClob(parameterName, reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(String parameterName, Reader reader, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setNClob(parameterName, reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNString(String parameterName, String value) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setNString(parameterName, value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + /** + * @see java.sql.CallableStatement#getCharacterStream(int) + */ + public Reader getCharacterStream(int parameterIndex) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getCharacterStream(parameterIndex); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + /** + * @see java.sql.CallableStatement#getCharacterStream(java.lang.String) + */ + public Reader getCharacterStream(String parameterName) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getCharacterStream(parameterName); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + /** + * @see java.sql.CallableStatement#getNCharacterStream(int) + */ + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getNCharacterStream(parameterIndex); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + /** + * @see java.sql.CallableStatement#getNCharacterStream(java.lang.String) + */ + public Reader getNCharacterStream(String parameterName) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getNCharacterStream(parameterName); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + /** + * @see java.sql.CallableStatement#getNClob(java.lang.String) + */ + public NClob getNClob(String parameterName) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getNClob(parameterName); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + /** + * @see java.sql.CallableStatement#getNString(java.lang.String) + */ + public String getNString(String parameterName) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getNString(parameterName); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + public void setAsciiStream(String parameterName, InputStream x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setAsciiStream(parameterName, x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setAsciiStream(parameterName, x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBinaryStream(String parameterName, InputStream x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setBinaryStream(parameterName, x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setBinaryStream(parameterName, x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBlob(String parameterName, InputStream x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setBlob(parameterName, x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBlob(String parameterName, InputStream x, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setBlob(parameterName, x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBlob(String parameterName, Blob x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setBlob(parameterName, x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setCharacterStream(String parameterName, Reader reader) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setCharacterStream(parameterName, reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setCharacterStream(parameterName, reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setClob(String parameterName, Clob x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setClob(parameterName, x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setClob(String parameterName, Reader reader) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setClob(parameterName, reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setClob(String parameterName, Reader reader, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setClob(parameterName, reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNCharacterStream(String parameterName, Reader reader) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setNCharacterStream(parameterName, reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((CallableStatement) this.wrappedStmt).setNCharacterStream(parameterName, reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public NClob getNClob(int parameterIndex) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getNClob(parameterIndex); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + public String getNString(int parameterIndex) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getNString(parameterIndex); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } + + public RowId getRowId(int parameterIndex) throws SQLException { + try { + if (this.wrappedStmt != null) { + return ((CallableStatement) this.wrappedStmt).getRowId(parameterIndex); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return null; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,337 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.NClob; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.SQLError; + +/** + */ +public class JDBC4ConnectionWrapper extends ConnectionWrapper { + + /** + * Construct a new LogicalHandle and set instance variables + * + * @param mysqlPooledConnection + * reference to object that instantiated this object + * @param mysqlConnection + * physical connection to db + * + * @throws SQLException + * if an error occurs. + */ + public JDBC4ConnectionWrapper(MysqlPooledConnection mysqlPooledConnection, + com.mysql.jdbc.Connection mysqlConnection, boolean forXa) + throws SQLException { + super(mysqlPooledConnection, mysqlConnection, forXa); + } + + public void close() throws SQLException { + try { + super.close(); + } finally { + this.unwrappedInterfaces = null; + } + } + + public SQLXML createSQLXML() throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).createSQLXML(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + public java.sql.Array createArrayOf(String typeName, Object[] elements) + throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).createArrayOf(typeName, + elements); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + public Struct createStruct(String typeName, Object[] attributes) + throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).createStruct(typeName, + attributes); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + public Properties getClientInfo() throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).getClientInfo(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + public String getClientInfo(String name) throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).getClientInfo(name); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + /** + * Returns true if the connection has not been closed and is still valid. + * The driver shall submit a query on the connection or use some other + * mechanism that positively verifies the connection is still valid when + * this method is called. + *

    + * The query submitted by the driver to validate the connection shall be + * executed in the context of the current transaction. + * + * @param timeout - + * The time in seconds to wait for the database operation used to + * validate the connection to complete. If the timeout period + * expires before the operation completes, this method returns + * false. A value of 0 indicates a timeout is not applied to the + * database operation. + *

    + * @return true if the connection is valid, false otherwise + * @exception SQLException + * if the value supplied for timeout is less + * then 0 + * @since 1.6 + */ + public synchronized boolean isValid(int timeout) throws SQLException { + try { + return ((java.sql.Connection) this.mc).isValid(timeout); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return false; // never reached, but compiler can't tell + } + + public void setClientInfo(Properties properties) + throws SQLClientInfoException { + try { + checkClosed(); + + ((java.sql.Connection) this.mc).setClientInfo(properties); + } catch (SQLException sqlException) { + try { + checkAndFireConnectionError(sqlException); + } catch (SQLException sqlEx2) { + SQLClientInfoException clientEx = new SQLClientInfoException(); + clientEx.initCause(sqlEx2); + + throw clientEx; + } + } + } + + public void setClientInfo(String name, String value) + throws SQLClientInfoException { + try { + checkClosed(); + + ((java.sql.Connection) this.mc).setClientInfo(name, value); + } catch (SQLException sqlException) { + try { + checkAndFireConnectionError(sqlException); + } catch (SQLException sqlEx2) { + SQLClientInfoException clientEx = new SQLClientInfoException(); + clientEx.initCause(sqlEx2); + + throw clientEx; + } + } + } + + /** + * Returns true if this either implements the interface argument or is + * directly or indirectly a wrapper for an object that does. Returns false + * otherwise. If this implements the interface then return true, else if + * this is a wrapper then return the result of recursively calling + * isWrapperFor on the wrapped object. If this does not + * implement the interface and is not a wrapper, return false. This method + * should be implemented as a low-cost operation compared to + * unwrap so that callers can use this method to avoid + * expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument + * should succeed. + * + * @param interfaces + * a Class defining an interface. + * @return true if this implements the interface or directly or indirectly + * wraps an object that does. + * @throws java.sql.SQLException + * if an error occurs while determining whether this is a + * wrapper for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + checkClosed(); + + boolean isInstance = iface.isInstance(this); + + if (isInstance) { + return true; + } + + return (iface.getName().equals("com.mysql.jdbc.Connection") || + iface.getName().equals("com.mysql.jdbc.ConnectionProperties")); + } + + /** + * Returns an object that implements the given interface to allow access to + * non-standard methods, or standard methods not exposed by the proxy. The + * result may be either the object found to implement the interface or a + * proxy for that object. If the receiver implements the interface then that + * is the object. If the receiver is a wrapper and the wrapped object + * implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped + * object. If the receiver is not a wrapper and does not implement the + * interface, then an SQLException is thrown. + * + * @param iface + * A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the + * actual implementing object. + * @throws java.sql.SQLException + * If no object found that implements the interface + * @since 1.6 + */ + public synchronized T unwrap(java.lang.Class iface) + throws java.sql.SQLException { + try { + if ("java.sql.Connection".equals(iface.getName()) + || "java.sql.Wrapper.class".equals(iface.getName())) { + return iface.cast(this); + } + + if (unwrappedInterfaces == null) { + unwrappedInterfaces = new HashMap(); + } + + Object cachedUnwrapped = unwrappedInterfaces.get(iface); + + if (cachedUnwrapped == null) { + cachedUnwrapped = Proxy.newProxyInstance(this.mc.getClass() + .getClassLoader(), new Class[] { iface }, + new ConnectionErrorFiringInvocationHandler(this.mc)); + unwrappedInterfaces.put(iface, cachedUnwrapped); + } + + return iface.cast(cachedUnwrapped); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } + + /** + * @see java.sql.Connection#createBlob() + */ + public Blob createBlob() throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).createBlob(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + /** + * @see java.sql.Connection#createClob() + */ + public Clob createClob() throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).createClob(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } + + /** + * @see java.sql.Connection#createNClob() + */ + public NClob createNClob() throws SQLException { + checkClosed(); + + try { + return ((java.sql.Connection) this.mc).createNClob(); + } catch (SQLException sqlException) { + checkAndFireConnectionError(sqlException); + } + + return null; // never reached, but compiler can't tell + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4MysqlPooledConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4MysqlPooledConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4MysqlPooledConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,107 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.sql.SQLException; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.sql.StatementEvent; +import javax.sql.StatementEventListener; + + +/** + * This class is used to wrap and return a physical connection within a logical + * handle. It also registers and notifies ConnectionEventListeners of any + * ConnectionEvents + * + * @see javax.sql.PooledConnection + * @see org.gjt.mm.mysql.jdbc2.optional.LogicalHandle + * @author Todd Wolff + */ +public class JDBC4MysqlPooledConnection extends MysqlPooledConnection { + + private Map statementEventListeners; + + public JDBC4MysqlPooledConnection(com.mysql.jdbc.Connection connection) { + super(connection); + + this.statementEventListeners = new HashMap(); + } + + public synchronized void close() throws SQLException { + super.close(); + + if (this.statementEventListeners != null) { + this.statementEventListeners.clear(); + + this.statementEventListeners = null; + } + } + + + /** + * Registers a StatementEventListener with this PooledConnection object. Components that + * wish to be notified when PreparedStatements created by the + * connection are closed or are detected to be invalid may use this method + * to register a StatementEventListener with this PooledConnection object. + *

    + * @param listener an component which implements the StatementEventListener + * interface that is to be registered with this PooledConnection object + *

    + * @since 1.6 + */ + public void addStatementEventListener(StatementEventListener listener) { + synchronized (this.statementEventListeners) { + this.statementEventListeners.put(listener, listener); + } + } + + /** + * Removes the specified StatementEventListener from the list of + * components that will be notified when the driver detects that a + * PreparedStatement has been closed or is invalid. + *

    + * @param listener the component which implements the + * StatementEventListener interface that was previously + * registered with this PooledConnection object + *

    + * @since 1.6 + */ + public void removeStatementEventListener(StatementEventListener listener) { + synchronized (this.statementEventListeners) { + this.statementEventListeners.remove(listener); + } + } + + void fireStatementEvent(StatementEvent event) throws SQLException { + synchronized (this.statementEventListeners) { + for (StatementEventListener listener : this.statementEventListeners.keySet()) { + listener.statementClosed(event); + } + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4MysqlXAConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4MysqlXAConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4MysqlXAConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,99 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.sql.SQLException; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.sql.StatementEvent; +import javax.sql.StatementEventListener; + +import com.mysql.jdbc.ConnectionImpl; + +public class JDBC4MysqlXAConnection extends MysqlXAConnection { + + private Map statementEventListeners; + + public JDBC4MysqlXAConnection(ConnectionImpl connection, boolean logXaCommands) throws SQLException { + super(connection, logXaCommands); + + this.statementEventListeners = new HashMap(); + } + + public synchronized void close() throws SQLException { + super.close(); + + if (this.statementEventListeners != null) { + this.statementEventListeners.clear(); + + this.statementEventListeners = null; + } + } + + + /** + * Registers a StatementEventListener with this PooledConnection object. Components that + * wish to be notified when PreparedStatements created by the + * connection are closed or are detected to be invalid may use this method + * to register a StatementEventListener with this PooledConnection object. + *

    + * @param listener an component which implements the StatementEventListener + * interface that is to be registered with this PooledConnection object + *

    + * @since 1.6 + */ + public void addStatementEventListener(StatementEventListener listener) { + synchronized (this.statementEventListeners) { + this.statementEventListeners.put(listener, listener); + } + } + + /** + * Removes the specified StatementEventListener from the list of + * components that will be notified when the driver detects that a + * PreparedStatement has been closed or is invalid. + *

    + * @param listener the component which implements the + * StatementEventListener interface that was previously + * registered with this PooledConnection object + *

    + * @since 1.6 + */ + public void removeStatementEventListener(StatementEventListener listener) { + synchronized (this.statementEventListeners) { + this.statementEventListeners.remove(listener); + } + } + + void fireStatementEvent(StatementEvent event) throws SQLException { + synchronized (this.statementEventListeners) { + for (StatementEventListener listener : this.statementEventListeners.keySet()) { + listener.statementClosed(event); + } + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,536 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.io.InputStream; +import java.io.Reader; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.RowId; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Statement; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.sql.StatementEvent; + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.jdbc2.optional.ConnectionWrapper; +import com.mysql.jdbc.jdbc2.optional.MysqlPooledConnection; + +/** + */ +public class JDBC4PreparedStatementWrapper extends PreparedStatementWrapper { + + public JDBC4PreparedStatementWrapper(ConnectionWrapper c, MysqlPooledConnection conn, + PreparedStatement toWrap) { + super(c, conn, toWrap); + } + + public synchronized void close() throws SQLException { + if (this.pooledConnection == null) { + // no-op + return; + } + + MysqlPooledConnection con = this.pooledConnection; // we need this + // later... + + try { + super.close(); + } finally { + try { + StatementEvent e = new StatementEvent(con, this); + // todo: pull this all up into base classes when we support *only* JDK6 or newer + if (con instanceof JDBC4MysqlPooledConnection) { + ((JDBC4MysqlPooledConnection) con).fireStatementEvent(e); + } else if (con instanceof JDBC4MysqlXAConnection) { + ((JDBC4MysqlXAConnection) con).fireStatementEvent(e); + } else if (con instanceof JDBC4SuspendableXAConnection) { + ((JDBC4SuspendableXAConnection) con).fireStatementEvent(e); + } + } finally { + this.unwrappedInterfaces = null; + } + } + } + + public boolean isClosed() throws SQLException { + try { + if (this.wrappedStmt != null) { + return this.wrappedStmt.isClosed(); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return false; // never get here - compiler can't tell + } + + public void setPoolable(boolean poolable) throws SQLException { + try { + if (this.wrappedStmt != null) { + this.wrappedStmt.setPoolable(poolable); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public boolean isPoolable() throws SQLException { + try { + if (this.wrappedStmt != null) { + return this.wrappedStmt.isPoolable(); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return false; // never get here - compiler can't tell + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setRowId(parameterIndex, + x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, + value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setSQLXML(parameterIndex, + xmlObject); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + + public void setNString(int parameterIndex, + String value) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNString(parameterIndex, + value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNCharacterStream(int parameterIndex, + Reader value, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNCharacterStream(parameterIndex, + value, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setClob(int parameterIndex, + Reader reader, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex, + reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBlob(int parameterIndex, + InputStream inputStream, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex, + inputStream, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(int parameterIndex, + Reader reader, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, + reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setAsciiStream(int parameterIndex, + InputStream x, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setAsciiStream(parameterIndex, + x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBinaryStream(int parameterIndex, + InputStream x, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBinaryStream(parameterIndex, + x, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setCharacterStream(int parameterIndex, + Reader reader, + long length) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setCharacterStream(parameterIndex, + reader, length); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setAsciiStream(int parameterIndex, + InputStream x) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setAsciiStream(parameterIndex, + x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setBinaryStream(int parameterIndex, + InputStream x) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBinaryStream(parameterIndex, + x); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setCharacterStream(int parameterIndex, + Reader reader) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setCharacterStream(parameterIndex, + reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + } + + public void setNCharacterStream(int parameterIndex, + Reader value) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNCharacterStream(parameterIndex, + value); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + } + + public void setClob(int parameterIndex, + Reader reader) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex, + reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + } + + public void setBlob(int parameterIndex, + InputStream inputStream) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex, + inputStream); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public void setNClob(int parameterIndex, + Reader reader) + throws SQLException { + try { + if (this.wrappedStmt != null) { + ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, + reader); + } else { + throw SQLError.createSQLException( + "No operations allowed after statement closed", + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + /** + * Returns true if this either implements the interface argument or is + * directly or indirectly a wrapper for an object that does. Returns false + * otherwise. If this implements the interface then return true, else if + * this is a wrapper then return the result of recursively calling + * isWrapperFor on the wrapped object. If this does not + * implement the interface and is not a wrapper, return false. This method + * should be implemented as a low-cost operation compared to + * unwrap so that callers can use this method to avoid + * expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument + * should succeed. + * + * @param interfaces + * a Class defining an interface. + * @return true if this implements the interface or directly or indirectly + * wraps an object that does. + * @throws java.sql.SQLException + * if an error occurs while determining whether this is a + * wrapper for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + + boolean isInstance = iface.isInstance(this); + + if (isInstance) { + return true; + } + + String interfaceClassName = iface.getName(); + + return (interfaceClassName.equals("com.mysql.jdbc.Statement") + || interfaceClassName.equals("java.sql.Statement") + || interfaceClassName.equals("java.sql.PreparedStatement") + || interfaceClassName.equals("java.sql.Wrapper")); + } + + /** + * Returns an object that implements the given interface to allow access to + * non-standard methods, or standard methods not exposed by the proxy. The + * result may be either the object found to implement the interface or a + * proxy for that object. If the receiver implements the interface then that + * is the object. If the receiver is a wrapper and the wrapped object + * implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped + * object. If the receiver is not a wrapper and does not implement the + * interface, then an SQLException is thrown. + * + * @param iface + * A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the + * actual implementing object. + * @throws java.sql.SQLException + * If no object found that implements the interface + * @since 1.6 + */ + public synchronized T unwrap(java.lang.Class iface) + throws java.sql.SQLException { + try { + if ("java.sql.Statement".equals(iface.getName()) + || "java.sql.PreparedStatement".equals(iface.getName()) + || "java.sql.Wrapper.class".equals(iface.getName())) { + return iface.cast(this); + } + + if (unwrappedInterfaces == null) { + unwrappedInterfaces = new HashMap(); + } + + Object cachedUnwrapped = unwrappedInterfaces.get(iface); + + if (cachedUnwrapped == null) { + if (cachedUnwrapped == null) { + cachedUnwrapped = Proxy.newProxyInstance( + this.wrappedStmt.getClass().getClassLoader(), + new Class[] { iface }, + new ConnectionErrorFiringInvocationHandler(this.wrappedStmt)); + unwrappedInterfaces.put(iface, cachedUnwrapped); + } + unwrappedInterfaces.put(iface, cachedUnwrapped); + } + + return iface.cast(cachedUnwrapped); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,197 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.NClob; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.jdbc2.optional.ConnectionWrapper; +import com.mysql.jdbc.jdbc2.optional.MysqlPooledConnection; + +/** + */ +public class JDBC4StatementWrapper extends StatementWrapper { + + public JDBC4StatementWrapper(ConnectionWrapper c, + MysqlPooledConnection conn, + Statement toWrap) { + super(c, conn, toWrap); + } + + public void close() throws SQLException { + try { + super.close(); + } finally { + this.unwrappedInterfaces = null; + } + } + + public boolean isClosed() throws SQLException { + try { + if (this.wrappedStmt != null) { + return this.wrappedStmt.isClosed(); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return false; // We never get here, compiler can't tell + } + + public void setPoolable(boolean poolable) throws SQLException { + try { + if (this.wrappedStmt != null) { + this.wrappedStmt.setPoolable(poolable); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + } + + public boolean isPoolable() throws SQLException { + try { + if (this.wrappedStmt != null) { + return this.wrappedStmt.isPoolable(); + } else { + throw SQLError.createSQLException("Statement already closed", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } catch (SQLException sqlEx) { + checkAndFireConnectionError(sqlEx); + } + + return false; // We never get here, compiler can't tell + } + + /** + * Returns true if this either implements the interface argument or is + * directly or indirectly a wrapper for an object that does. Returns false + * otherwise. If this implements the interface then return true, else if + * this is a wrapper then return the result of recursively calling + * isWrapperFor on the wrapped object. If this does not + * implement the interface and is not a wrapper, return false. This method + * should be implemented as a low-cost operation compared to + * unwrap so that callers can use this method to avoid + * expensive unwrap calls that may fail. If this method + * returns true then calling unwrap with the same argument + * should succeed. + * + * @param interfaces + * a Class defining an interface. + * @return true if this implements the interface or directly or indirectly + * wraps an object that does. + * @throws java.sql.SQLException + * if an error occurs while determining whether this is a + * wrapper for an object with the given interface. + * @since 1.6 + */ + public boolean isWrapperFor(Class iface) throws SQLException { + + boolean isInstance = iface.isInstance(this); + + if (isInstance) { + return true; + } + + String interfaceClassName = iface.getName(); + + return (interfaceClassName.equals("com.mysql.jdbc.Statement") + || interfaceClassName.equals("java.sql.Statement") + || interfaceClassName.equals("java.sql.Wrapper")); + } + + /** + * Returns an object that implements the given interface to allow access to + * non-standard methods, or standard methods not exposed by the proxy. The + * result may be either the object found to implement the interface or a + * proxy for that object. If the receiver implements the interface then that + * is the object. If the receiver is a wrapper and the wrapped object + * implements the interface then that is the object. Otherwise the object is + * the result of calling unwrap recursively on the wrapped + * object. If the receiver is not a wrapper and does not implement the + * interface, then an SQLException is thrown. + * + * @param iface + * A Class defining an interface that the result must implement. + * @return an object that implements the interface. May be a proxy for the + * actual implementing object. + * @throws java.sql.SQLException + * If no object found that implements the interface + * @since 1.6 + */ + public synchronized T unwrap(java.lang.Class iface) + throws java.sql.SQLException { + try { + if ("java.sql.Statement".equals(iface.getName()) + || "java.sql.Wrapper.class".equals(iface.getName())) { + return iface.cast(this); + } + + if (unwrappedInterfaces == null) { + unwrappedInterfaces = new HashMap(); + } + + Object cachedUnwrapped = unwrappedInterfaces.get(iface); + + if (cachedUnwrapped == null) { + cachedUnwrapped = Proxy.newProxyInstance( + this.wrappedStmt.getClass().getClassLoader(), + new Class[] { iface }, + new ConnectionErrorFiringInvocationHandler(this.wrappedStmt)); + unwrappedInterfaces.put(iface, cachedUnwrapped); + } + + return iface.cast(cachedUnwrapped); + } catch (ClassCastException cce) { + throw SQLError.createSQLException("Unable to unwrap to " + + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); + } + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4SuspendableXAConnection.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4SuspendableXAConnection.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/JDBC4SuspendableXAConnection.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,99 @@ +/* + Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jdbc2.optional; + +import java.sql.SQLException; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.sql.StatementEvent; +import javax.sql.StatementEventListener; + +import com.mysql.jdbc.ConnectionImpl; + +public class JDBC4SuspendableXAConnection extends SuspendableXAConnection { + + private Map statementEventListeners; + + public JDBC4SuspendableXAConnection(ConnectionImpl connection) throws SQLException { + super(connection); + + this.statementEventListeners = new HashMap(); + } + + public synchronized void close() throws SQLException { + super.close(); + + if (this.statementEventListeners != null) { + this.statementEventListeners.clear(); + + this.statementEventListeners = null; + } + } + + + /** + * Registers a StatementEventListener with this PooledConnection object. Components that + * wish to be notified when PreparedStatements created by the + * connection are closed or are detected to be invalid may use this method + * to register a StatementEventListener with this PooledConnection object. + *

    + * @param listener an component which implements the StatementEventListener + * interface that is to be registered with this PooledConnection object + *

    + * @since 1.6 + */ + public void addStatementEventListener(StatementEventListener listener) { + synchronized (this.statementEventListeners) { + this.statementEventListeners.put(listener, listener); + } + } + + /** + * Removes the specified StatementEventListener from the list of + * components that will be notified when the driver detects that a + * PreparedStatement has been closed or is invalid. + *

    + * @param listener the component which implements the + * StatementEventListener interface that was previously + * registered with this PooledConnection object + *

    + * @since 1.6 + */ + public void removeStatementEventListener(StatementEventListener listener) { + synchronized (this.statementEventListeners) { + this.statementEventListeners.remove(listener); + } + } + + void fireStatementEvent(StatementEvent event) throws SQLException { + synchronized (this.statementEventListeners) { + for (StatementEventListener listener : this.statementEventListeners.keySet()) { + listener.statementClosed(event); + } + } + } +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlConnectionPoolDataSource.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlConnectionPoolDataSource.java (.../MysqlConnectionPoolDataSource.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlConnectionPoolDataSource.java (.../MysqlConnectionPoolDataSource.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; import java.sql.Connection; @@ -43,6 +42,9 @@ */ public class MysqlConnectionPoolDataSource extends MysqlDataSource implements ConnectionPoolDataSource { + + static final long serialVersionUID = -7767325445592304961L; + // ~ Methods // ---------------------------------------------------------------- @@ -56,7 +58,7 @@ public synchronized PooledConnection getPooledConnection() throws SQLException { Connection connection = getConnection(); - MysqlPooledConnection mysqlPooledConnection = new MysqlPooledConnection( + MysqlPooledConnection mysqlPooledConnection = MysqlPooledConnection.getInstance( (com.mysql.jdbc.Connection)connection); return mysqlPooledConnection; @@ -77,7 +79,7 @@ public synchronized PooledConnection getPooledConnection(String s, String s1) throws SQLException { Connection connection = getConnection(s, s1); - MysqlPooledConnection mysqlPooledConnection = new MysqlPooledConnection( + MysqlPooledConnection mysqlPooledConnection = MysqlPooledConnection.getInstance( (com.mysql.jdbc.Connection)connection); return mysqlPooledConnection; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlDataSource.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlDataSource.java (.../MysqlDataSource.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlDataSource.java (.../MysqlDataSource.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,68 +1,67 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; -import com.mysql.jdbc.ConnectionProperties; -import com.mysql.jdbc.NonRegisteringDriver; - import java.io.PrintWriter; import java.io.Serializable; - import java.sql.SQLException; - +import java.util.Iterator; import java.util.Properties; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.StringRefAddr; - import javax.sql.DataSource; +import com.mysql.jdbc.ConnectionPropertiesImpl; +import com.mysql.jdbc.NonRegisteringDriver; + /** * A JNDI DataSource for a Mysql JDBC connection * * @author Mark Matthews */ -public class MysqlDataSource extends ConnectionProperties implements - DataSource, Referenceable, Serializable { +public class MysqlDataSource extends ConnectionPropertiesImpl implements + DataSource, Referenceable, Serializable { + + static final long serialVersionUID = -5515846944416881264L; + /** The driver to create connections with */ - protected static com.mysql.jdbc.Driver mysqlDriver = null; + protected final static NonRegisteringDriver mysqlDriver; static { try { - mysqlDriver = (com.mysql.jdbc.Driver) Class.forName( - "com.mysql.jdbc.Driver").newInstance(); + mysqlDriver = new NonRegisteringDriver(); } catch (Exception E) { throw new RuntimeException( "Can not load Driver class com.mysql.jdbc.Driver"); } } /** Log stream */ - protected PrintWriter logWriter = null; + protected transient PrintWriter logWriter = null; /** Database Name */ protected String databaseName = null; @@ -422,6 +421,31 @@ jdbcUrlToUse = this.url; } + // + // URL should take precedence over properties + // + + Properties urlProps = mysqlDriver.parseURL(jdbcUrlToUse, null); + urlProps.remove(NonRegisteringDriver.DBNAME_PROPERTY_KEY); + urlProps.remove(NonRegisteringDriver.HOST_PROPERTY_KEY); + urlProps.remove(NonRegisteringDriver.PORT_PROPERTY_KEY); + + Iterator keys = urlProps.keySet().iterator(); + + while (keys.hasNext()) { + String key = (String)keys.next(); + + props.setProperty(key, urlProps.getProperty(key)); + } + return mysqlDriver.connect(jdbcUrlToUse, props); } +// +// public boolean isWrapperFor(Class iface) throws SQLException { +// throw SQLError.notImplemented(); +// } +// +// public T unwrap(Class iface) throws SQLException { +// throw SQLError.notImplemented(); +// } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlDataSourceFactory.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlDataSourceFactory.java (.../MysqlDataSourceFactory.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlDataSourceFactory.java (.../MysqlDataSourceFactory.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; import java.util.Hashtable; @@ -72,7 +71,7 @@ * DOCUMENT ME! */ public Object getObjectInstance(Object refObj, Name nm, Context ctx, - Hashtable env) throws Exception { + Hashtable env) throws Exception { Reference ref = (Reference) refObj; String className = ref.getClassName(); @@ -148,4 +147,4 @@ return asString; } -} +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java (.../MysqlPooledConnection.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java (.../MysqlPooledConnection.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,40 +1,42 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; +import java.lang.reflect.Constructor; import java.sql.Connection; import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; -import java.util.Enumeration; -import java.util.Hashtable; - import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.PooledConnection; +import com.mysql.jdbc.ExceptionInterceptor; import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Util; /** * This class is used to wrap and return a physical connection within a logical @@ -47,6 +49,37 @@ */ public class MysqlPooledConnection implements PooledConnection { + private static final Constructor JDBC_4_POOLED_CONNECTION_WRAPPER_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_POOLED_CONNECTION_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4MysqlPooledConnection") + .getConstructor( + new Class[] { com.mysql.jdbc.Connection.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_POOLED_CONNECTION_WRAPPER_CTOR = null; + } + } + + protected static MysqlPooledConnection getInstance(com.mysql.jdbc.Connection connection) throws SQLException { + if (!Util.isJdbc4()) { + return new MysqlPooledConnection(connection); + } + + return (MysqlPooledConnection) Util.handleNewInstance( + JDBC_4_POOLED_CONNECTION_WRAPPER_CTOR, new Object[] { + connection}, connection.getExceptionInterceptor()); + } + /** * The flag for an exception being thrown. */ @@ -59,11 +92,13 @@ // ~ Instance/static variables ............................................. - private Hashtable eventListeners; + private Map connectionEventListeners; private Connection logicalHandle; private com.mysql.jdbc.Connection physicalConn; + + private ExceptionInterceptor exceptionInterceptor; // ~ Constructors .......................................................... @@ -76,11 +111,10 @@ public MysqlPooledConnection(com.mysql.jdbc.Connection connection) { this.logicalHandle = null; this.physicalConn = connection; - this.eventListeners = new Hashtable(10); + this.connectionEventListeners = new HashMap(); + this.exceptionInterceptor = this.physicalConn.getExceptionInterceptor(); } - // ~ Methods ............................................................... - /** * Adds ConnectionEventListeners to a hash table to be used for notification * of ConnectionEvents @@ -91,8 +125,8 @@ public synchronized void addConnectionEventListener( ConnectionEventListener connectioneventlistener) { - if (this.eventListeners != null) { - this.eventListeners.put(connectioneventlistener, + if (this.connectionEventListeners != null) { + this.connectionEventListeners.put(connectioneventlistener, connectioneventlistener); } } @@ -107,8 +141,8 @@ public synchronized void removeConnectionEventListener( ConnectionEventListener connectioneventlistener) { - if (this.eventListeners != null) { - this.eventListeners.remove(connectioneventlistener); + if (this.connectionEventListeners != null) { + this.connectionEventListeners.remove(connectioneventlistener); } } @@ -129,8 +163,8 @@ if (this.physicalConn == null) { SQLException sqlException = SQLError.createSQLException( - "Physical Connection doesn't exist"); - callListener(CONNECTION_ERROR_EVENT, sqlException); + "Physical Connection doesn't exist", this.exceptionInterceptor); + callConnectionEventListeners(CONNECTION_ERROR_EVENT, sqlException); throw sqlException; } @@ -142,12 +176,14 @@ } if (resetServerState) { - ((com.mysql.jdbc.Connection) this.physicalConn).resetServerState(); + this.physicalConn.resetServerState(); } - this.logicalHandle = new ConnectionWrapper(this, this.physicalConn, forXa); + this.logicalHandle = ConnectionWrapper.getInstance(this, + this.physicalConn, + forXa); } catch (SQLException sqlException) { - callListener(CONNECTION_ERROR_EVENT, sqlException); + callConnectionEventListeners(CONNECTION_ERROR_EVENT, sqlException); throw sqlException; } @@ -165,9 +201,15 @@ public synchronized void close() throws SQLException { if (this.physicalConn != null) { this.physicalConn.close(); + + this.physicalConn = null; } - - this.physicalConn = null; + + if (this.connectionEventListeners != null) { + this.connectionEventListeners.clear(); + + this.connectionEventListeners = null; + } } /** @@ -182,31 +224,33 @@ * @param sqlException * the exception being thrown */ - protected synchronized void callListener(int eventType, + protected synchronized void callConnectionEventListeners(int eventType, SQLException sqlException) { - if (this.eventListeners == null) { + if (this.connectionEventListeners == null) { return; } - Enumeration enumeration = this.eventListeners.keys(); + Iterator> iterator = this.connectionEventListeners.entrySet().iterator(); + ConnectionEvent connectionevent = new ConnectionEvent(this, sqlException); - while (enumeration.hasMoreElements()) { + while (iterator.hasNext()) { - ConnectionEventListener connectioneventlistener = (ConnectionEventListener) enumeration - .nextElement(); - ConnectionEventListener connectioneventlistener1 = (ConnectionEventListener) this.eventListeners - .get(connectioneventlistener); + ConnectionEventListener connectioneventlistener = iterator.next().getValue(); if (eventType == CONNECTION_CLOSED_EVENT) { - connectioneventlistener1.connectionClosed(connectionevent); + connectioneventlistener.connectionClosed(connectionevent); } else if (eventType == CONNECTION_ERROR_EVENT) { - connectioneventlistener1 + connectioneventlistener .connectionErrorOccurred(connectionevent); } } } + + protected ExceptionInterceptor getExceptionInterceptor() { + return this.exceptionInterceptor; + } } \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java (.../MysqlXAConnection.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java (.../MysqlXAConnection.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,29 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ + package com.mysql.jdbc.jdbc2.optional; +import java.lang.reflect.Constructor; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -37,6 +39,9 @@ import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.StringUtils; +import com.mysql.jdbc.Util; import com.mysql.jdbc.log.Log; /* @@ -61,31 +66,67 @@ public class MysqlXAConnection extends MysqlPooledConnection implements XAConnection, XAResource { - private com.mysql.jdbc.Connection underlyingConnection; + private static final int MAX_COMMAND_LENGTH = 300; + + private com.mysql.jdbc.ConnectionImpl underlyingConnection; - private final static Map MYSQL_ERROR_CODES_TO_XA_ERROR_CODES; + private final static Map MYSQL_ERROR_CODES_TO_XA_ERROR_CODES; private Log log; protected boolean logXaCommands; static { - HashMap temp = new HashMap(); + HashMap temp = new HashMap(); - temp.put(new Integer(1397), new Integer(XAException.XAER_NOTA)); - temp.put(new Integer(1398), new Integer(XAException.XAER_INVAL)); - temp.put(new Integer(1399), new Integer(XAException.XAER_RMFAIL)); - temp.put(new Integer(1400), new Integer(XAException.XAER_OUTSIDE)); - temp.put(new Integer(1401), new Integer(XAException.XAER_RMERR)); - temp.put(new Integer(1402), new Integer(XAException.XA_RBROLLBACK)); + temp.put(Integer.valueOf(1397), Integer.valueOf(XAException.XAER_NOTA)); + temp.put(Integer.valueOf(1398), Integer.valueOf(XAException.XAER_INVAL)); + temp.put(Integer.valueOf(1399), Integer.valueOf(XAException.XAER_RMFAIL)); + temp.put(Integer.valueOf(1400), Integer.valueOf(XAException.XAER_OUTSIDE)); + temp.put(Integer.valueOf(1401), Integer.valueOf(XAException.XAER_RMERR)); + temp.put(Integer.valueOf(1402), Integer.valueOf(XAException.XA_RBROLLBACK)); + temp.put(Integer.valueOf(1440), Integer.valueOf(XAException.XAER_DUPID)); MYSQL_ERROR_CODES_TO_XA_ERROR_CODES = Collections.unmodifiableMap(temp); } + + private static final Constructor JDBC_4_XA_CONNECTION_WRAPPER_CTOR; + static { + if (Util.isJdbc4()) { + try { + JDBC_4_XA_CONNECTION_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4MysqlXAConnection") + .getConstructor( + new Class[] { ConnectionImpl.class, Boolean.TYPE }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_XA_CONNECTION_WRAPPER_CTOR = null; + } + } + + protected static MysqlXAConnection getInstance(ConnectionImpl mysqlConnection, + boolean logXaCommands) throws SQLException { + if (!Util.isJdbc4()) { + return new MysqlXAConnection(mysqlConnection, logXaCommands); + } + + return (MysqlXAConnection) Util.handleNewInstance( + JDBC_4_XA_CONNECTION_WRAPPER_CTOR, new Object[] { + mysqlConnection, + Boolean.valueOf(logXaCommands) }, mysqlConnection.getExceptionInterceptor()); + } + /** * @param connection */ - public MysqlXAConnection(com.mysql.jdbc.Connection connection, boolean logXaCommands) + public MysqlXAConnection(ConnectionImpl connection, boolean logXaCommands) throws SQLException { super(connection); this.underlyingConnection = connection; @@ -120,7 +161,6 @@ * XAER_RMERR and XAER_RMFAIL. */ public int getTransactionTimeout() throws XAException { - // TODO Auto-generated method stub return 0; } @@ -146,7 +186,6 @@ * XAER_RMERR, XAER_RMFAIL, or XAER_INVAL. */ public boolean setTransactionTimeout(int arg0) throws XAException { - // TODO Auto-generated method stub return false; } @@ -261,7 +300,7 @@ ResultSet rs = null; Statement stmt = null; - List recoveredXidList = new ArrayList(); + List recoveredXidList = new ArrayList(); try { // TODO: Cache this for lifetime of XAConnection @@ -343,9 +382,9 @@ * XAER_PROTO. */ public int prepare(Xid xid) throws XAException { - StringBuffer commandBuf = new StringBuffer(); + StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA PREPARE "); - commandBuf.append(xidToString(xid)); + appendXid(commandBuf, xid); dispatchCommand(commandBuf.toString()); @@ -364,7 +403,7 @@ * XAER_PROTO. */ public void forget(Xid xid) throws XAException { - // TODO Auto-generated method stub + // mysql doesn't support this } /** @@ -385,9 +424,9 @@ * has released all held resources. */ public void rollback(Xid xid) throws XAException { - StringBuffer commandBuf = new StringBuffer(); + StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA ROLLBACK "); - commandBuf.append(xidToString(xid)); + appendXid(commandBuf, xid); try { dispatchCommand(commandBuf.toString()); @@ -424,20 +463,20 @@ * or XA_RB*. */ public void end(Xid xid, int flags) throws XAException { - StringBuffer commandBuf = new StringBuffer(); + StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA END "); - commandBuf.append(xidToString(xid)); + appendXid(commandBuf, xid); switch (flags) { - case TMSUCCESS: - break; // no-op - case TMSUSPEND: - commandBuf.append(" SUSPEND"); - break; - case TMFAIL: - break; // no-op - default: - throw new XAException(XAException.XAER_INVAL); + case TMSUCCESS: + break; // no-op + case TMSUSPEND: + commandBuf.append(" SUSPEND"); + break; + case TMFAIL: + break; // no-op + default: + throw new XAException(XAException.XAER_INVAL); } dispatchCommand(commandBuf.toString()); @@ -467,26 +506,26 @@ * XAER_INVAL, or XAER_PROTO. */ public void start(Xid xid, int flags) throws XAException { - StringBuffer commandBuf = new StringBuffer(); + StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA START "); - commandBuf.append(xidToString(xid)); + appendXid(commandBuf, xid); switch (flags) { - case TMJOIN: - commandBuf.append(" JOIN"); - break; - case TMRESUME: - commandBuf.append(" RESUME"); - break; - case TMNOFLAGS: - // no-op - break; - default: - throw new XAException(XAException.XAER_INVAL); + case TMJOIN: + commandBuf.append(" JOIN"); + break; + case TMRESUME: + commandBuf.append(" RESUME"); + break; + case TMNOFLAGS: + // no-op + break; + default: + throw new XAException(XAException.XAER_INVAL); } dispatchCommand(commandBuf.toString()); - + this.underlyingConnection.setInGlobalTx(true); } @@ -512,9 +551,9 @@ */ public void commit(Xid xid, boolean onePhase) throws XAException { - StringBuffer commandBuf = new StringBuffer(); + StringBuilder commandBuf = new StringBuilder(MAX_COMMAND_LENGTH); commandBuf.append("XA COMMIT "); - commandBuf.append(xidToString(xid)); + appendXid(commandBuf, xid); if (onePhase) { commandBuf.append(" ONE PHASE"); @@ -537,7 +576,8 @@ // TODO: Cache this for lifetime of XAConnection stmt = this.underlyingConnection.createStatement(); - + + stmt.execute(command); ResultSet rs = stmt.getResultSet(); @@ -557,8 +597,8 @@ protected static XAException mapXAExceptionFromSQLException(SQLException sqlEx) { - Integer xaCode = (Integer) MYSQL_ERROR_CODES_TO_XA_ERROR_CODES - .get(new Integer(sqlEx.getErrorCode())); + Integer xaCode = MYSQL_ERROR_CODES_TO_XA_ERROR_CODES + .get(Integer.valueOf(sqlEx.getErrorCode())); if (xaCode != null) { return new MysqlXAException(xaCode.intValue(), sqlEx.getMessage(), null); @@ -568,62 +608,21 @@ return new MysqlXAException(sqlEx.getMessage(), null); } - private static String xidToString(Xid xid) { + private static void appendXid(StringBuilder builder, Xid xid) { byte[] gtrid = xid.getGlobalTransactionId(); - byte[] btrid = xid.getBranchQualifier(); - int lengthAsString = 6; // for (0x and ,) * 2 - if (gtrid != null) { - lengthAsString += (2 * gtrid.length); + StringUtils.appendAsHex(builder, gtrid); } + builder.append(','); if (btrid != null) { - lengthAsString += (2 * btrid.length); + StringUtils.appendAsHex(builder, btrid); } - String formatIdInHex = Integer.toHexString(xid.getFormatId()); - - lengthAsString += formatIdInHex.length(); - lengthAsString += 3; // for the '.' after formatId - - StringBuffer asString = new StringBuffer(lengthAsString); - - asString.append("0x"); - - if (gtrid != null) { - for (int i = 0; i < gtrid.length; i++) { - String asHex = Integer.toHexString(gtrid[i] & 0xff); - - if (asHex.length() == 1) { - asString.append("0"); - } - - asString.append(asHex); - } - } - - asString.append(","); - - if (btrid != null) { - asString.append("0x"); - - for (int i = 0; i < btrid.length; i++) { - String asHex = Integer.toHexString(btrid[i] & 0xff); - - if (asHex.length() == 1) { - asString.append("0"); - } - - asString.append(asHex); - } - } - - asString.append(",0x"); - asString.append(formatIdInHex); - - return asString.toString(); + builder.append(','); + StringUtils.appendAsHex(builder, xid.getFormatId()); } /* Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXADataSource.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXADataSource.java (.../MysqlXADataSource.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXADataSource.java (.../MysqlXADataSource.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; import java.sql.Connection; @@ -39,6 +38,8 @@ public class MysqlXADataSource extends MysqlDataSource implements javax.sql.XADataSource { + static final long serialVersionUID = 7911390333152247455L; + /** * @see javax.sql.XADataSource#getXAConnection() */ @@ -52,10 +53,10 @@ /** * @see javax.sql.XADataSource#getXAConnection(String, String) */ - public XAConnection getXAConnection(String user, String password) + public XAConnection getXAConnection(String u, String p) throws SQLException { - Connection conn = getConnection(user, password); + Connection conn = getConnection(u, p); return wrapConnection(conn); } @@ -67,9 +68,9 @@ private XAConnection wrapConnection(Connection conn) throws SQLException { if (getPinGlobalTxToPhysicalConnection() || ((com.mysql.jdbc.Connection)conn).getPinGlobalTxToPhysicalConnection()) { - return new SuspendableXAConnection((com.mysql.jdbc.Connection) conn); + return SuspendableXAConnection.getInstance((com.mysql.jdbc.ConnectionImpl) conn); } - return new MysqlXAConnection((com.mysql.jdbc.Connection) conn, getLogXaCommands()); + return MysqlXAConnection.getInstance((com.mysql.jdbc.ConnectionImpl) conn, getLogXaCommands()); } } \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java (.../MysqlXAException.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java (.../MysqlXAException.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,23 +1,23 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ @@ -33,7 +33,7 @@ private static final long serialVersionUID = -9075817535836563004L; private String message; - private String xidAsString; + protected String xidAsString; public MysqlXAException(int errorCode, String message, String xidAsString) { super(errorCode); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXid.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXid.java (.../MysqlXid.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/MysqlXid.java (.../MysqlXid.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,25 +1,25 @@ /* - Copyright (C) 2005 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA -*/ + */ package com.mysql.jdbc.jdbc2.optional; @@ -80,12 +80,10 @@ } return true; - } else { - return false; } - } else { - return false; } + + return false; } public byte[] getBranchQualifier() { Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java (.../PreparedStatementWrapper.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java (.../PreparedStatementWrapper.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,38 +1,33 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; -import com.mysql.jdbc.SQLError; - import java.io.InputStream; import java.io.Reader; - +import java.lang.reflect.Constructor; import java.math.BigDecimal; - import java.net.URL; - import java.sql.Array; import java.sql.Blob; import java.sql.Clob; @@ -45,9 +40,11 @@ import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; - import java.util.Calendar; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Util; + /** * Wraps prepared statements so that errors can be reported correctly to * ConnectionEventListeners. @@ -59,6 +56,42 @@ */ public class PreparedStatementWrapper extends StatementWrapper implements PreparedStatement { + private static final Constructor JDBC_4_PREPARED_STATEMENT_WRAPPER_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_PREPARED_STATEMENT_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper").getConstructor( + new Class[] { ConnectionWrapper.class, + MysqlPooledConnection.class, + PreparedStatement.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_PREPARED_STATEMENT_WRAPPER_CTOR = null; + } + } + + protected static PreparedStatementWrapper getInstance(ConnectionWrapper c, + MysqlPooledConnection conn, + PreparedStatement toWrap) throws SQLException { + if (!Util.isJdbc4()) { + return new PreparedStatementWrapper(c, + conn, toWrap); + } + + return (PreparedStatementWrapper) Util.handleNewInstance( + JDBC_4_PREPARED_STATEMENT_WRAPPER_CTOR, + new Object[] {c, + conn, toWrap }, conn.getExceptionInterceptor()); + } + PreparedStatementWrapper(ConnectionWrapper c, MysqlPooledConnection conn, PreparedStatement toWrap) { super(c, conn, toWrap); @@ -77,7 +110,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -99,7 +132,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -120,7 +153,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -142,7 +175,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -162,7 +195,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -182,7 +215,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -202,7 +235,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -222,7 +255,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -244,7 +277,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -264,7 +297,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -284,7 +317,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -306,7 +339,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -326,7 +359,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -346,7 +379,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -366,7 +399,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -386,7 +419,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -406,7 +439,7 @@ throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -427,7 +460,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -448,7 +481,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -468,7 +501,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -489,7 +522,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -511,7 +544,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -532,7 +565,7 @@ throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -553,7 +586,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -573,7 +606,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -593,7 +626,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -613,7 +646,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -635,7 +668,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -656,7 +689,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -678,7 +711,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -698,7 +731,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -731,7 +764,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -750,7 +783,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -769,7 +802,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -789,13 +822,13 @@ throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } return false; // we actually never get here, but the compiler can't - // figure + // figure // that out } @@ -811,20 +844,20 @@ ResultSet rs = ((PreparedStatement) this.wrappedStmt) .executeQuery(); - ((com.mysql.jdbc.ResultSet) rs).setWrapperStatement(this); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).setWrapperStatement(this); return rs; } throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } return null; // we actually never get here, but the compiler can't - // figure + // figure // that out } @@ -842,7 +875,7 @@ throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -851,4 +884,358 @@ // that out } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(super.toString()); + + if (this.wrappedStmt != null) { + buf.append(": "); //$NON-NLS-1$ + try { + buf.append(((com.mysql.jdbc.PreparedStatement) this.wrappedStmt).asSql()); + } catch(SQLException sqlEx) { + buf.append("EXCEPTION: " + sqlEx.toString()); + } + } + + return buf.toString(); + } +// +// public void setAsciiStream(int parameterIndex, InputStream x) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setAsciiStream( +// parameterIndex, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setAsciiStream(int parameterIndex, InputStream x, long length) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setAsciiStream( +// parameterIndex, x, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBinaryStream(int parameterIndex, InputStream x) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setBinaryStream( +// parameterIndex, x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBinaryStream(int parameterIndex, InputStream x, long length) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setBinaryStream( +// parameterIndex, x, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(int parameterIndex, InputStream inputStream) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex, +// inputStream); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setBlob(int parameterIndex, InputStream inputStream, long length) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex, +// inputStream, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setCharacterStream(int parameterIndex, Reader reader) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setCharacterStream( +// parameterIndex, reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setCharacterStream(int parameterIndex, Reader reader, +// long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setCharacterStream( +// parameterIndex, reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(int parameterIndex, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex, +// reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setClob(int parameterIndex, Reader reader, long length) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex, +// reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNCharacterStream(int parameterIndex, Reader value) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setNCharacterStream( +// parameterIndex, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNCharacterStream(int parameterIndex, Reader value, +// long length) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setNCharacterStream( +// parameterIndex, value, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(int parameterIndex, NClob value) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, +// value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(int parameterIndex, Reader reader) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, +// reader); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNClob(int parameterIndex, Reader reader, long length) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, +// reader, length); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setNString(int parameterIndex, String value) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setNString( +// parameterIndex, value); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setRowId(int parameterIndex, RowId x) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setRowId(parameterIndex, +// x); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public void setSQLXML(int parameterIndex, SQLXML xmlObject) +// throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setSQLXML( +// parameterIndex, xmlObject); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public boolean isClosed() throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((PreparedStatement) this.wrappedStmt).isClosed(); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return true; +// } +// +// public boolean isPoolable() throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// return ((PreparedStatement) this.wrappedStmt).isPoolable(); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// +// return false; +// } +// +// public void setPoolable(boolean poolable) throws SQLException { +// try { +// if (this.wrappedStmt != null) { +// ((PreparedStatement) this.wrappedStmt).setPoolable(poolable); +// } else { +// throw SQLError.createSQLException( +// "No operations allowed after statement closed", +// SQLError.SQL_STATE_GENERAL_ERROR); +// } +// } catch (SQLException sqlEx) { +// checkAndFireConnectionError(sqlEx); +// } +// } +// +// public boolean isWrapperFor(Class arg0) throws SQLException { +// throw SQLError.notImplemented(); +// } +// +// public Object unwrap(Class arg0) throws SQLException { +// throw SQLError.notImplemented(); +// } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java (.../StatementWrapper.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java (.../StatementWrapper.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,37 +1,38 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; -import com.mysql.jdbc.SQLError; - +import java.lang.reflect.Constructor; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; +import com.mysql.jdbc.SQLError; +import com.mysql.jdbc.Util; + /** * Wraps statements so that errors can be reported correctly to * ConnectionEventListeners. @@ -42,13 +43,49 @@ * Exp $ */ public class StatementWrapper extends WrapperBase implements Statement { + private static final Constructor JDBC_4_STATEMENT_WRAPPER_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_STATEMENT_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4StatementWrapper").getConstructor( + new Class[] { ConnectionWrapper.class, + MysqlPooledConnection.class, + Statement.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_STATEMENT_WRAPPER_CTOR = null; + } + } + + protected static StatementWrapper getInstance(ConnectionWrapper c, + MysqlPooledConnection conn, + Statement toWrap) throws SQLException { + if (!Util.isJdbc4()) { + return new StatementWrapper(c, + conn, toWrap); + } + + return (StatementWrapper) Util.handleNewInstance( + JDBC_4_STATEMENT_WRAPPER_CTOR, + new Object[] {c, + conn, toWrap }, conn.getExceptionInterceptor()); + } + protected Statement wrappedStmt; protected ConnectionWrapper wrappedConn; - protected StatementWrapper(ConnectionWrapper c, MysqlPooledConnection conn, + public StatementWrapper(ConnectionWrapper c, MysqlPooledConnection conn, Statement toWrap) { - this.pooledConnection = conn; + super(conn); this.wrappedStmt = toWrap; this.wrappedConn = c; } @@ -65,7 +102,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -87,7 +124,7 @@ this.wrappedStmt.setCursorName(name); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -105,7 +142,7 @@ this.wrappedStmt.setEscapeProcessing(enable); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -123,7 +160,7 @@ this.wrappedStmt.setFetchDirection(direction); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -142,7 +179,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -164,7 +201,7 @@ this.wrappedStmt.setFetchSize(rows); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -183,7 +220,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -205,7 +242,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -227,7 +264,7 @@ this.wrappedStmt.setMaxFieldSize(max); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -246,7 +283,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -267,7 +304,7 @@ this.wrappedStmt.setMaxRows(max); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -286,7 +323,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -308,7 +345,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -328,7 +365,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -347,7 +384,7 @@ this.wrappedStmt.setQueryTimeout(seconds); } else { throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); @@ -366,7 +403,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -383,14 +420,15 @@ try { if (this.wrappedStmt != null) { ResultSet rs = this.wrappedStmt.getResultSet(); - - ((com.mysql.jdbc.ResultSet) rs).setWrapperStatement(this); - + + if (rs != null) { + ((com.mysql.jdbc.ResultSetInternalMethods) rs).setWrapperStatement(this); + } return rs; } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -410,7 +448,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -430,7 +468,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -450,7 +488,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -470,7 +508,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -490,7 +528,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -589,7 +627,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -612,7 +650,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -636,7 +674,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -659,7 +697,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -682,7 +720,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -703,13 +741,13 @@ if (this.wrappedStmt != null) { ResultSet rs = this.wrappedStmt.executeQuery(sql); - ((com.mysql.jdbc.ResultSet) rs).setWrapperStatement(this); + ((com.mysql.jdbc.ResultSetInternalMethods) rs).setWrapperStatement(this); return rs; } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -733,7 +771,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -756,7 +794,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -780,7 +818,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -802,7 +840,7 @@ } throw SQLError.createSQLException("Statement already closed", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, this.exceptionInterceptor); } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); } @@ -820,7 +858,7 @@ } else { throw SQLError.createSQLException( "No operations allowed after statement closed", - SQLError.SQL_STATE_GENERAL_ERROR); + SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); } } catch (SQLException sqlEx) { checkAndFireConnectionError(sqlEx); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/SuspendableXAConnection.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/SuspendableXAConnection.java (.../SuspendableXAConnection.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/SuspendableXAConnection.java (.../SuspendableXAConnection.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,6 +1,30 @@ +/* + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + package com.mysql.jdbc.jdbc2.optional; +import java.lang.reflect.Constructor; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; @@ -10,38 +34,71 @@ import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; -import com.mysql.jdbc.Connection; +import com.mysql.jdbc.ConnectionImpl; +import com.mysql.jdbc.Util; public class SuspendableXAConnection extends MysqlPooledConnection implements XAConnection, XAResource { - public SuspendableXAConnection(Connection connection) { + private static final Constructor JDBC_4_XA_CONNECTION_WRAPPER_CTOR; + + static { + if (Util.isJdbc4()) { + try { + JDBC_4_XA_CONNECTION_WRAPPER_CTOR = Class.forName( + "com.mysql.jdbc.jdbc2.optional.JDBC4SuspendableXAConnection") + .getConstructor( + new Class[] { ConnectionImpl.class }); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + JDBC_4_XA_CONNECTION_WRAPPER_CTOR = null; + } + } + + protected static SuspendableXAConnection getInstance(ConnectionImpl mysqlConnection) throws SQLException { + if (!Util.isJdbc4()) { + return new SuspendableXAConnection(mysqlConnection); + } + + return (SuspendableXAConnection) Util.handleNewInstance( + JDBC_4_XA_CONNECTION_WRAPPER_CTOR, new Object[] { + mysqlConnection}, mysqlConnection.getExceptionInterceptor()); + } + + public SuspendableXAConnection(ConnectionImpl connection) { super(connection); this.underlyingConnection = connection; } - private static final Map XIDS_TO_PHYSICAL_CONNECTIONS = - new HashMap(); + private static final Map XIDS_TO_PHYSICAL_CONNECTIONS = + new HashMap(); private Xid currentXid; private XAConnection currentXAConnection; private XAResource currentXAResource; - private Connection underlyingConnection; + private ConnectionImpl underlyingConnection; - private static synchronized XAConnection findConnectionForXid(Connection connectionToWrap, Xid xid) + private static synchronized XAConnection findConnectionForXid(ConnectionImpl connectionToWrap, Xid xid) throws SQLException { // TODO: check for same GTRID, but different BQUALs...MySQL doesn't allow this yet // Note, we don't need to check for XIDs here, because MySQL itself will complain // with a XAER_NOTA if need be. - XAConnection conn = (XAConnection)XIDS_TO_PHYSICAL_CONNECTIONS.get(xid); + XAConnection conn = XIDS_TO_PHYSICAL_CONNECTIONS.get(xid); if (conn == null) { - conn = new MysqlXAConnection(connectionToWrap, + conn = new MysqlXAConnection(connectionToWrap, connectionToWrap.getLogXaCommands()); + XIDS_TO_PHYSICAL_CONNECTIONS.put(xid, conn); } return conn; @@ -91,7 +148,6 @@ } public int getTransactionTimeout() throws XAException { - // TODO Auto-generated method stub return 0; } @@ -115,7 +171,6 @@ } public boolean setTransactionTimeout(int arg0) throws XAException { - // TODO Auto-generated method stub return false; } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/WrapperBase.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/WrapperBase.java (.../WrapperBase.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jdbc2/optional/WrapperBase.java (.../WrapperBase.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,36 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.jdbc2.optional; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.sql.SQLException; +import java.util.Map; +import com.mysql.jdbc.ExceptionInterceptor; import com.mysql.jdbc.SQLError; /** @@ -51,11 +56,77 @@ if (this.pooledConnection != null) { if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE.equals(sqlEx .getSQLState())) { - this.pooledConnection.callListener( + this.pooledConnection.callConnectionEventListeners( MysqlPooledConnection.CONNECTION_ERROR_EVENT, sqlEx); } } throw sqlEx; } + + protected Map unwrappedInterfaces = null; + protected ExceptionInterceptor exceptionInterceptor; + + protected WrapperBase(MysqlPooledConnection pooledConnection) { + this.pooledConnection = pooledConnection; + this.exceptionInterceptor = this.pooledConnection.getExceptionInterceptor(); + } + + protected class ConnectionErrorFiringInvocationHandler implements InvocationHandler { + Object invokeOn = null; + + public ConnectionErrorFiringInvocationHandler(Object toInvokeOn) { + invokeOn = toInvokeOn; + } + + public Object invoke(Object proxy, Method method, + Object[] args) throws Throwable { + Object result = null; + + try { + result = method.invoke(invokeOn, args); + + if (result != null) { + result = proxyIfInterfaceIsJdbc(result, + result.getClass()); + } + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof SQLException) { + checkAndFireConnectionError((SQLException) e + .getTargetException()); + } else { + throw e; + } + } + + return result; + } + + /** + * Recursively checks for interfaces on the given object to determine + * if it implements a java.sql interface, and if so, proxies the + * instance so that we can catch and fire SQL errors. + * @param toProxy + * @param clazz + * @return + */ + private Object proxyIfInterfaceIsJdbc(Object toProxy, Class clazz) { + Class[] interfaces = clazz.getInterfaces(); + + for (Class iclass : interfaces) { + String packageName = iclass.getPackage().getName(); + + if ("java.sql".equals(packageName) || + "javax.sql".equals(packageName)) { + return Proxy.newProxyInstance(toProxy.getClass() + .getClassLoader(), interfaces, + new ConnectionErrorFiringInvocationHandler(toProxy)); + } + + return proxyIfInterfaceIsJdbc(toProxy, iclass); + } + + return toProxy; + } + } } \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/LoadBalanceConnectionGroupManager.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/LoadBalanceConnectionGroupManager.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/LoadBalanceConnectionGroupManager.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,120 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jmx; + +import java.lang.management.ManagementFactory; +import java.sql.SQLException; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import com.mysql.jdbc.ConnectionGroupManager; +import com.mysql.jdbc.SQLError; + +public class LoadBalanceConnectionGroupManager implements + LoadBalanceConnectionGroupManagerMBean { + + private boolean isJmxRegistered = false; + + public LoadBalanceConnectionGroupManager(){ + + } + + public synchronized void registerJmx() throws SQLException { + if(this.isJmxRegistered){ + return; + } + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + try { + ObjectName name = new ObjectName("com.mysql.jdbc.jmx:type=LoadBalanceConnectionGroupManager"); + mbs.registerMBean(this, name); + this.isJmxRegistered = true; + } catch (Exception e) { + throw SQLError.createSQLException("Uable to register load-balance management bean with JMX", null, e, null); + } + + } + + public void addHost(String group, String host, boolean forExisting) { + try { + ConnectionGroupManager.addHost(group, host, forExisting); + } catch (Exception e){ + e.printStackTrace(); + } + } + + public int getActiveHostCount(String group) { + return ConnectionGroupManager.getActiveHostCount(group); + } + + public long getActiveLogicalConnectionCount(String group) { + return ConnectionGroupManager.getActiveLogicalConnectionCount(group); + } + + public long getActivePhysicalConnectionCount(String group) { + return ConnectionGroupManager.getActivePhysicalConnectionCount(group); + } + + public int getTotalHostCount(String group) { + return ConnectionGroupManager.getTotalHostCount(group); + + } + + public long getTotalLogicalConnectionCount(String group) { + return ConnectionGroupManager.getTotalLogicalConnectionCount(group); + + } + + public long getTotalPhysicalConnectionCount(String group) { + return ConnectionGroupManager.getTotalPhysicalConnectionCount(group); + + } + + public long getTotalTransactionCount(String group) { + return ConnectionGroupManager.getTotalTransactionCount(group); + + } + + public void removeHost(String group, String host) throws SQLException { + ConnectionGroupManager.removeHost(group, host); + + } + + public String getActiveHostsList(String group) { + return ConnectionGroupManager.getActiveHostLists(group); + } + + public String getRegisteredConnectionGroups() { + return ConnectionGroupManager.getRegisteredConnectionGroups(); + } + + public void stopNewConnectionsToHost(String group, String host) + throws SQLException { + ConnectionGroupManager.removeHost(group, host); + + } + + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/LoadBalanceConnectionGroupManagerMBean.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/LoadBalanceConnectionGroupManagerMBean.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/LoadBalanceConnectionGroupManagerMBean.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,55 @@ +/* + Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jmx; + +import java.sql.SQLException; + + +public interface LoadBalanceConnectionGroupManagerMBean { + + public abstract int getActiveHostCount(String group); + + public abstract int getTotalHostCount(String group); + + public abstract long getTotalLogicalConnectionCount(String group); + + public abstract long getActiveLogicalConnectionCount(String group); + + public abstract long getActivePhysicalConnectionCount(String group); + + public abstract long getTotalPhysicalConnectionCount(String group); + + public abstract long getTotalTransactionCount(String group); + + public abstract void removeHost(String group, String host) throws SQLException; + + public abstract void stopNewConnectionsToHost(String group, String host) throws SQLException; + + public abstract void addHost(String group, String host, boolean forExisting); + + public abstract String getActiveHostsList(String group); + + public abstract String getRegisteredConnectionGroups(); + +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/ReplicationGroupManager.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/ReplicationGroupManager.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/ReplicationGroupManager.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,137 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jmx; + +import java.lang.management.ManagementFactory; +import java.sql.SQLException; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import com.mysql.jdbc.ReplicationConnectionGroup; +import com.mysql.jdbc.ReplicationConnectionGroupManager; +import com.mysql.jdbc.SQLError; + +public class ReplicationGroupManager implements ReplicationGroupManagerMBean { + private boolean isJmxRegistered = false; + + public synchronized void registerJmx() throws SQLException { + if(this.isJmxRegistered){ + return; + } + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + try { + ObjectName name = new ObjectName("com.mysql.jdbc.jmx:type=ReplicationGroupManager"); + mbs.registerMBean(this, name); + this.isJmxRegistered = true; + } catch (Exception e) { + throw SQLError.createSQLException("Unable to register replication host management bean with JMX", null, e, null); + } + + } + + public void addSlaveHost(String groupFilter, String host) throws SQLException { + ReplicationConnectionGroupManager.addSlaveHost(groupFilter, host); + } + + public void removeSlaveHost(String groupFilter, String host) throws SQLException { + ReplicationConnectionGroupManager.removeSlaveHost(groupFilter, host); + } + + public void promoteSlaveToMaster(String groupFilter, String host) throws SQLException { + ReplicationConnectionGroupManager.promoteSlaveToMaster(groupFilter, host); + + } + + public void removeMasterHost(String groupFilter, String host) + throws SQLException { + ReplicationConnectionGroupManager.removeMasterHost(groupFilter, host); + + } + + public String getMasterHostsList(String group) { + StringBuffer sb = new StringBuffer(""); + boolean found = false; + for(String host : ReplicationConnectionGroupManager.getMasterHosts(group)) { + if(found) { + sb.append(","); + } + found = true; + sb.append(host); + } + return sb.toString(); + } + + public String getSlaveHostsList(String group) { + StringBuffer sb = new StringBuffer(""); + boolean found = false; + for(String host : ReplicationConnectionGroupManager.getSlaveHosts(group)) { + if(found) { + sb.append(","); + } + found = true; + sb.append(host); + } + return sb.toString(); + + } + + public String getRegisteredConnectionGroups() { + StringBuffer sb = new StringBuffer(""); + boolean found = false; + for(ReplicationConnectionGroup group : ReplicationConnectionGroupManager.getGroupsMatching(null)) { + if(found) { + sb.append(","); + } + found = true; + sb.append(group.getGroupName()); + } + return sb.toString(); + } + + public int getActiveMasterHostCount(String group) { + return ReplicationConnectionGroupManager.getMasterHosts(group).size(); + } + + public int getActiveSlaveHostCount(String group) { + return ReplicationConnectionGroupManager.getSlaveHosts(group).size(); + } + + + public int getSlavePromotionCount(String group) { + return ReplicationConnectionGroupManager.getNumberOfMasterPromotion(group); + } + + public long getTotalLogicalConnectionCount(String group) { + return ReplicationConnectionGroupManager.getTotalConnectionCount(group); + } + + public long getActiveLogicalConnectionCount(String group) { + return ReplicationConnectionGroupManager.getActiveConnectionCount(group); + } + + + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/ReplicationGroupManagerMBean.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/ReplicationGroupManagerMBean.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/jmx/ReplicationGroupManagerMBean.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,55 @@ +/* + Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.jmx; + +import java.sql.SQLException; + +public interface ReplicationGroupManagerMBean { + + public abstract void addSlaveHost(String groupFilter, String host) throws SQLException; + + public abstract void removeSlaveHost(String groupFilter, String host) throws SQLException; + + public abstract void promoteSlaveToMaster(String groupFilter, String host) throws SQLException; + + public abstract void removeMasterHost(String groupFilter, String host) throws SQLException; + + public abstract String getMasterHostsList(String group); + + public abstract String getSlaveHostsList(String group); + + public abstract String getRegisteredConnectionGroups(); + + public abstract int getActiveMasterHostCount(String group); + + public abstract int getActiveSlaveHostCount(String group); + + public abstract int getSlavePromotionCount(String group); + + public abstract long getTotalLogicalConnectionCount(String group); + + public abstract long getActiveLogicalConnectionCount(String group); + + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Jdk14Logger.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Jdk14Logger.java (.../Jdk14Logger.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Jdk14Logger.java (.../Jdk14Logger.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,34 +1,33 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.log; -import com.mysql.jdbc.profiler.ProfilerEvent; - import java.util.logging.Level; import java.util.logging.Logger; +import com.mysql.jdbc.profiler.ProfilerEvent; + /** * Logging functionality for JDK1.4 * @@ -263,8 +262,8 @@ String messageAsString = null; String callerMethodName = "N/A"; String callerClassName = "N/A"; - int lineNumber = 0; - String fileName = "N/A"; + //int lineNumber = 0; + //String fileName = "N/A"; if (msg instanceof ProfilerEvent) { messageAsString = LogUtils.expandProfilerEventIfNecessary(msg) @@ -279,8 +278,8 @@ if (frameIdx != 0) { callerClassName = locations[frameIdx].getClassName(); callerMethodName = locations[frameIdx].getMethodName(); - lineNumber = locations[frameIdx].getLineNumber(); - fileName = locations[frameIdx].getFileName(); + //lineNumber = locations[frameIdx].getLineNumber(); + //fileName = locations[frameIdx].getFileName(); } messageAsString = String.valueOf(msg); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Log.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Log.java (.../Log.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Log.java (.../Log.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.log; /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/LogFactory.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/LogFactory.java (.../LogFactory.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/LogFactory.java (.../LogFactory.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,33 +1,33 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.log; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.sql.SQLException; +import com.mysql.jdbc.ExceptionInterceptor; import com.mysql.jdbc.SQLError; /** @@ -51,55 +51,81 @@ * @throws SQLException * if unable to create a logger instance */ - public static Log getLogger(String className, String instanceName) + public static Log getLogger(String className, String instanceName, ExceptionInterceptor exceptionInterceptor) throws SQLException { if (className == null) { throw SQLError.createSQLException("Logger class can not be NULL", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } if (instanceName == null) { - throw SQLError.createSQLException("Logger instance name can not be NULL", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + throw SQLError.createSQLException( + "Logger instance name can not be NULL", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); } try { - Class loggerClass = null; - + Class loggerClass = null; + try { loggerClass = Class.forName(className); } catch (ClassNotFoundException nfe) { - loggerClass = Class.forName(Log.class.getPackage().getName() + "." + className); + loggerClass = Class.forName(Log.class.getPackage().getName() + + "." + className); } - - Constructor constructor = loggerClass + + Constructor constructor = loggerClass .getConstructor(new Class[] { String.class }); return (Log) constructor.newInstance(new Object[] { instanceName }); } catch (ClassNotFoundException cnfe) { - throw SQLError.createSQLException("Unable to load class for logger '" - + className + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLException sqlEx = SQLError.createSQLException( + "Unable to load class for logger '" + className + "'", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + sqlEx.initCause(cnfe); + + throw sqlEx; } catch (NoSuchMethodException nsme) { - throw SQLError.createSQLException( - "Logger class does not have a single-arg constructor that takes an instance name", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLException sqlEx = SQLError + .createSQLException( + "Logger class does not have a single-arg constructor that takes an instance name", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + sqlEx.initCause(nsme); + + throw sqlEx; } catch (InstantiationException inse) { - throw SQLError.createSQLException("Unable to instantiate logger class '" - + className + "', exception in constructor?", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLException sqlEx = SQLError.createSQLException( + "Unable to instantiate logger class '" + className + + "', exception in constructor?", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + sqlEx.initCause(inse); + + throw sqlEx; } catch (InvocationTargetException ite) { - throw SQLError.createSQLException("Unable to instantiate logger class '" - + className + "', exception in constructor?", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLException sqlEx = SQLError.createSQLException( + "Unable to instantiate logger class '" + className + + "', exception in constructor?", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + sqlEx.initCause(ite); + + throw sqlEx; } catch (IllegalAccessException iae) { - throw SQLError.createSQLException("Unable to instantiate logger class '" - + className + "', constructor not public", - SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLException sqlEx = SQLError.createSQLException( + "Unable to instantiate logger class '" + className + + "', constructor not public", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + sqlEx.initCause(iae); + + throw sqlEx; } catch (ClassCastException cce) { - throw SQLError.createSQLException("Logger class '" + className - + "' does not implement the '" + Log.class.getName() - + "' interface", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); + SQLException sqlEx = SQLError.createSQLException("Logger class '" + + className + "' does not implement the '" + + Log.class.getName() + "' interface", + SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); + sqlEx.initCause(cce); + + throw sqlEx; } } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/LogUtils.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/LogUtils.java (.../LogUtils.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/LogUtils.java (.../LogUtils.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,23 +1,24 @@ /* - Copyright (C) 2005-2007 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ package com.mysql.jdbc.log; @@ -42,16 +43,14 @@ ProfilerEvent evt = (ProfilerEvent) possibleProfilerEvent; - Throwable locationException = evt.getEventCreationPoint(); + String locationInformation = evt.getEventCreationPointAsString(); - if (locationException == null) { - locationException = new Throwable(); + if (locationInformation == null) { + locationInformation = Util.stackTraceToString(new Throwable()); } msgBuf.append("Profiler Event: ["); - boolean appendLocationInfo = false; - switch (evt.getEventType()) { case ProfilerEvent.TYPE_EXECUTE: msgBuf.append("EXECUTE"); @@ -80,22 +79,20 @@ case ProfilerEvent.TYPE_WARN: msgBuf.append("WARN"); - appendLocationInfo = true; - + break; case ProfilerEvent.TYPE_SLOW_QUERY: msgBuf.append("SLOW QUERY"); - appendLocationInfo = false; - + break; default: msgBuf.append("UNKNOWN"); } msgBuf.append("] "); - msgBuf.append(findCallingClassAndMethod(locationException)); + msgBuf.append(locationInformation); msgBuf.append(" duration: "); msgBuf.append(evt.getEventDuration()); msgBuf.append(" "); @@ -114,19 +111,12 @@ msgBuf.append(evtMessage); } - if (appendLocationInfo) { - msgBuf - .append("\n\nFull stack trace of location where event occurred:\n\n"); - msgBuf.append(Util.stackTraceToString(locationException)); - msgBuf.append("\n"); - } - return msgBuf; } return possibleProfilerEvent; } - + public static String findCallingClassAndMethod(Throwable t) { String stackTraceAsString = Util.stackTraceToString(t); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/NullLogger.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/NullLogger.java (.../NullLogger.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/NullLogger.java (.../NullLogger.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.log; /** Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Slf4JLogger.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Slf4JLogger.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/Slf4JLogger.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,108 @@ +/* + Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.log; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Slf4JLogger implements Log { + private Logger log; + + public Slf4JLogger(String name) { + log = LoggerFactory.getLogger(name); + } + + public boolean isDebugEnabled() { + return log.isDebugEnabled(); + } + + public boolean isErrorEnabled() { + return log.isErrorEnabled(); + } + + public boolean isFatalEnabled() { + return log.isErrorEnabled(); + } + + public boolean isInfoEnabled() { + return log.isInfoEnabled(); + } + + public boolean isTraceEnabled() { + return log.isTraceEnabled(); + } + + public boolean isWarnEnabled() { + return log.isWarnEnabled(); + } + + public void logDebug(Object msg) { + log.debug(msg.toString()); + } + + public void logDebug(Object msg, Throwable thrown) { + log.debug(msg.toString(), thrown); + } + + public void logError(Object msg) { + log.error(msg.toString()); + } + + public void logError(Object msg, Throwable thrown) { + log.error(msg.toString(), thrown); + } + + public void logFatal(Object msg) { + log.error(msg.toString()); + } + + public void logFatal(Object msg, Throwable thrown) { + log.error(msg.toString(), thrown); + } + + public void logInfo(Object msg) { + log.info(msg.toString()); + } + + public void logInfo(Object msg, Throwable thrown) { + log.info(msg.toString(), thrown); + } + + public void logTrace(Object msg) { + log.trace(msg.toString()); + } + + public void logTrace(Object msg, Throwable thrown) { + log.trace(msg.toString(), thrown); + } + + public void logWarn(Object msg) { + log.warn(msg.toString()); + } + + public void logWarn(Object msg, Throwable thrown) { + log.warn(msg.toString(), thrown); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/StandardLogger.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/StandardLogger.java (.../StandardLogger.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/log/StandardLogger.java (.../StandardLogger.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,34 +1,33 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.log; +import java.util.Date; + import com.mysql.jdbc.Util; import com.mysql.jdbc.profiler.ProfilerEvent; -import java.util.Date; - /** * Provides logging facilities for those platforms that don't have built-in * facilities. Simply logs messages to STDERR. @@ -64,6 +63,11 @@ this(name, false); } + /** + * + * @param name + * @param logLocationInfo + */ public StandardLogger(String name, boolean logLocationInfo) { this.logLocationInfo = logLocationInfo; } @@ -248,7 +252,7 @@ logInternal(WARN, message, exception); } - private void logInternal(int level, Object msg, Throwable exception) { + protected void logInternal(int level, Object msg, Throwable exception) { StringBuffer msgBuf = new StringBuffer(); msgBuf.append(new Date().toString()); msgBuf.append(" "); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,58 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.profiler; + +import java.sql.SQLException; +import java.util.Properties; + +import com.mysql.jdbc.Connection; +import com.mysql.jdbc.log.Log; + +/** + * A profile event handler that just logs to the standard + * logging mechanism of the JDBC driver. + * + */ +public class LoggingProfilerEventHandler implements ProfilerEventHandler { + private Log log; + + public LoggingProfilerEventHandler() {} + + public void consumeEvent(ProfilerEvent evt) { + if (evt.eventType == ProfilerEvent.TYPE_WARN) { + this.log.logWarn(evt); + } else { + this.log.logInfo(evt); + } + } + + public void destroy() { + this.log = null; + } + + public void init(Connection conn, Properties props) throws SQLException { + this.log = conn.getLog(); + } + +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/ProfilerEvent.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/ProfilerEvent.java (.../ProfilerEvent.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/ProfilerEvent.java (.../ProfilerEvent.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,31 +1,31 @@ /* - Copyright (C) 2002-2007 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA */ package com.mysql.jdbc.profiler; import java.util.Date; -import com.mysql.jdbc.Util; +import com.mysql.jdbc.StringUtils; /** * @author mmatthew @@ -131,11 +131,6 @@ protected int eventCreationPointIndex; /** - * Where was the event created (as a Throwable)? - */ - protected Throwable eventCreationPoint; - - /** * Where was the event created (as a string description of the * eventCreationPoint)? */ @@ -175,7 +170,7 @@ public ProfilerEvent(byte eventType, String hostName, String catalog, long connectionId, int statementId, int resultSetId, long eventCreationTime, long eventDuration, String durationUnits, - String eventCreationPointDesc, Throwable eventCreationPoint, + String eventCreationPointDesc, String eventCreationPoint, String message) { this.eventType = eventType; this.connectionId = connectionId; @@ -184,7 +179,6 @@ this.eventCreationTime = eventCreationTime; this.eventDuration = eventDuration; this.durationUnits = durationUnits; - this.eventCreationPoint = eventCreationPoint; this.eventCreationPointDesc = eventCreationPointDesc; this.message = message; } @@ -195,11 +189,6 @@ * @return a description of when this event was created. */ public String getEventCreationPointAsString() { - if (this.eventCreationPointDesc == null) { - this.eventCreationPointDesc = Util - .stackTraceToString(this.eventCreationPoint); - } - return this.eventCreationPointDesc; } @@ -298,7 +287,7 @@ pos += eventDurationUnits.length; } - int eventCreationPointIndex = readInt(buf, pos); + readInt(buf, pos); pos += 4; byte[] eventCreationAsBytes = readBytes(buf, pos); pos += 4; @@ -316,9 +305,9 @@ return new ProfilerEvent(eventType, "", "", connectionId, statementId, resultSetId, eventCreationTime, eventDuration, - new String(eventDurationUnits, "ISO8859_1"), - new String(eventCreationAsBytes, "ISO8859_1"), null, - new String(message, "ISO8859_1")); + StringUtils.toString(eventDurationUnits, "ISO8859_1"), + StringUtils.toString(eventCreationAsBytes, "ISO8859_1"), null, + StringUtils.toString(message, "ISO8859_1")); } /** @@ -337,29 +326,30 @@ getEventCreationPointAsString(); if (this.eventCreationPointDesc != null) { - eventCreationAsBytes = this.eventCreationPointDesc - .getBytes("ISO8859_1"); + eventCreationAsBytes = StringUtils.getBytes( + this.eventCreationPointDesc, "ISO8859_1"); len += (4 + eventCreationAsBytes.length); } else { len += 4; } byte[] messageAsBytes = null; - if (messageAsBytes != null) { - messageAsBytes = this.message.getBytes("ISO8859_1"); + if (this.message != null) { + messageAsBytes = StringUtils.getBytes(this.message, "ISO8859_1"); len += (4 + messageAsBytes.length); } else { len += 4; } byte[] durationUnitsAsBytes = null; - if (durationUnits != null) { - durationUnitsAsBytes = this.durationUnits.getBytes("ISO8859_1"); + if (this.durationUnits != null) { + durationUnitsAsBytes = StringUtils.getBytes(this.durationUnits, "ISO8859_1"); len += (4 + durationUnitsAsBytes.length); } else { len += 4; + durationUnitsAsBytes = StringUtils.getBytes("", "ISO8859_1"); } byte[] buf = new byte[len]; @@ -428,7 +418,7 @@ } private static long readLong(byte[] buf, int pos) { - return (long) (buf[pos++] & 0xff) | ((long) (buf[pos++] & 0xff) << 8) + return (buf[pos++] & 0xff) | ((long) (buf[pos++] & 0xff) << 8) | ((long) (buf[pos++] & 0xff) << 16) | ((long) (buf[pos++] & 0xff) << 24) | ((long) (buf[pos++] & 0xff) << 32) @@ -467,16 +457,6 @@ } /** - * Returns the point (as a Throwable stacktrace) where this event was - * created. - * - * @return the point where this event was created - */ - public Throwable getEventCreationPoint() { - return this.eventCreationPoint; - } - - /** * Returns the time (in System.currentTimeMillis() form) when this event was * created * @@ -537,4 +517,4 @@ public String getMessage() { return this.message; } -} +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/ProfilerEventHandler.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/ProfilerEventHandler.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/profiler/ProfilerEventHandler.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,31 @@ +/* + Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + */ + +package com.mysql.jdbc.profiler; + +import com.mysql.jdbc.Extension; + +public interface ProfilerEventHandler extends Extension { + + public void consumeEvent(ProfilerEvent evt); +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/Base64Decoder.java =================================================================== diff -u --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/Base64Decoder.java (revision 0) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/Base64Decoder.java (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,93 @@ +/* + Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + + + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . + + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + + + + */ +package com.mysql.jdbc.util; + +/** + * This decoder implements standard Base64 decoding except it allows + * and silently ignores non-base64 input characters (spaces, line breaks etc) + * + * Note: Java 6+ provide standard decoders + */ +public class Base64Decoder { + + /* + * -1 means non-base64 character + * -2 means padding + */ + private static byte[] decoderMap = new byte[] { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 + }; + + public static class IntWrapper { + public int value; + public IntWrapper(int value) { + this.value = value; + } + } + + private static byte getNextValidByte(byte[] in, IntWrapper pos, int maxPos) { + while (pos.value <= maxPos) { + if (in[pos.value] <= 127 && decoderMap[in[pos.value]] >= 0) { + return in[pos.value++]; + } + pos.value++; + } + // padding if reached max position + return '='; + } + + public static byte[] decode(byte[] in, int pos, int length) { + IntWrapper offset = new Base64Decoder.IntWrapper(pos); + byte[] sestet = new byte[4]; + + int outLen = (length * 3) / 4; // over-estimated if non-base64 characters present + byte[] octet = new byte[outLen]; + int octetId = 0; + + int maxPos = offset.value + length - 1; + while (offset.value <= maxPos) { + sestet[0] = decoderMap[getNextValidByte(in, offset, maxPos)]; + sestet[1] = decoderMap[getNextValidByte(in, offset, maxPos)]; + sestet[2] = decoderMap[getNextValidByte(in, offset, maxPos)]; + sestet[3] = decoderMap[getNextValidByte(in, offset, maxPos)]; + + if (sestet[1]!=-2) octet[octetId++] = (byte) ((sestet[0] << 2) | (sestet[1] >>> 4)); + if (sestet[2]!=-2) octet[octetId++] = (byte) (((sestet[1] & 0xf) << 4) | (sestet[2] >>> 2)); + if (sestet[3]!=-2) octet[octetId++] = (byte) (((sestet[2] & 3) << 6) | sestet[3]); + } + // return real-length value + byte[] out = new byte[octetId]; + System.arraycopy(octet,0,out,0,octetId); + return out; + } +} Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/BaseBugReport.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/BaseBugReport.java (.../BaseBugReport.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/BaseBugReport.java (.../BaseBugReport.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; import java.sql.Connection; @@ -34,7 +33,8 @@ * Base class to help file bug reports for Connector/J. * *

    - * MySQL AB + * MySQL AB, 2008 Sun Microsystems, 2009 Oracle Corporation + *

      * really *
    Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ErrorMappingsDocGenerator.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ErrorMappingsDocGenerator.java (.../ErrorMappingsDocGenerator.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ErrorMappingsDocGenerator.java (.../ErrorMappingsDocGenerator.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; import com.mysql.jdbc.SQLError; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/LRUCache.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/LRUCache.java (.../LRUCache.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/LRUCache.java (.../LRUCache.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; import java.util.LinkedHashMap; @@ -31,12 +30,12 @@ * @author Mark Matthews * @version $Id$ */ -public class LRUCache extends LinkedHashMap { +public class LRUCache extends LinkedHashMap { private static final long serialVersionUID = 1L; protected int maxElements; public LRUCache(int maxSize) { - super(maxSize); + super(maxSize, 0.75F, true); this.maxElements = maxSize; } @@ -45,7 +44,8 @@ * * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry) */ - protected boolean removeEldestEntry(Entry eldest) { + @Override + protected boolean removeEldestEntry(Entry eldest) { return (size() > this.maxElements); } } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/PropertiesDocGenerator.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/PropertiesDocGenerator.java (.../PropertiesDocGenerator.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/PropertiesDocGenerator.java (.../PropertiesDocGenerator.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,39 +1,40 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; import java.sql.SQLException; -import com.mysql.jdbc.ConnectionProperties; +import com.mysql.jdbc.ConnectionPropertiesImpl; /** * Creates docbook table of connection properties from ConnectionProperties * class. */ -public class PropertiesDocGenerator extends ConnectionProperties { +public class PropertiesDocGenerator extends ConnectionPropertiesImpl { + static final long serialVersionUID = -4869689139143855383L; + public static void main(String[] args) throws SQLException { System.out.println(new PropertiesDocGenerator().exposeAsXml()); } Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ReadAheadInputStream.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ReadAheadInputStream.java (.../ReadAheadInputStream.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ReadAheadInputStream.java (.../ReadAheadInputStream.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,25 +1,24 @@ /* - Copyright (C) 2002-2005 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - */ package com.mysql.jdbc.util; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ResultSetUtil.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ResultSetUtil.java (.../ResultSetUtil.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ResultSetUtil.java (.../ResultSetUtil.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; import java.sql.ResultSet; Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ServerController.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ServerController.java (.../ServerController.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/ServerController.java (.../ServerController.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,34 +1,31 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; import java.io.File; import java.io.IOException; - import java.util.Iterator; -import java.util.Locale; import java.util.Properties; import com.mysql.jdbc.StringUtils; @@ -145,11 +142,10 @@ public Process start() throws IOException { if (this.serverProcess != null) { throw new IllegalArgumentException("Server already started"); - } else { - this.serverProcess = Runtime.getRuntime().exec(getCommandLine()); - - return this.serverProcess; } + this.serverProcess = Runtime.getRuntime().exec(getCommandLine()); + + return this.serverProcess; } /** @@ -172,8 +168,7 @@ pathBuf.append(File.separator); } - String defaultsFilePath = getServerProps().getProperty( - DEFAULTS_FILE_KEY); + //String defaultsFilePath = getServerProps().getProperty(DEFAULTS_FILE_KEY); pathBuf.append("bin"); pathBuf.append(File.separator); @@ -292,7 +287,7 @@ if (this.serverProps != null) { - for (Iterator iter = this.serverProps.keySet().iterator(); iter + for (Iterator iter = this.serverProps.keySet().iterator(); iter .hasNext();) { String key = (String) iter.next(); String value = this.serverProps.getProperty(key); Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/TimezoneDump.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/TimezoneDump.java (.../TimezoneDump.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/TimezoneDump.java (.../TimezoneDump.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,34 +1,33 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package com.mysql.jdbc.util; -import com.mysql.jdbc.TimeUtil; - import java.sql.DriverManager; import java.sql.ResultSet; +import com.mysql.jdbc.TimeUtil; + /** * Dumps the timezone of the MySQL server represented by the JDBC url given on * the commandline (or localhost/test if none provided). @@ -71,16 +70,23 @@ Class.forName("com.mysql.jdbc.Driver").newInstance(); - ResultSet rs = DriverManager.getConnection(jdbcUrl).createStatement() - .executeQuery("SHOW VARIABLES LIKE 'timezone'"); + ResultSet rs = null; + + try { + rs = DriverManager.getConnection(jdbcUrl).createStatement().executeQuery("SHOW VARIABLES LIKE 'timezone'"); - while (rs.next()) { - String timezoneFromServer = rs.getString(2); - System.out.println("MySQL timezone name: " + timezoneFromServer); - - String canonicalTimezone = TimeUtil - .getCanoncialTimezone(timezoneFromServer); - System.out.println("Java timezone name: " + canonicalTimezone); + while (rs.next()) { + String timezoneFromServer = rs.getString(2); + System.out.println("MySQL timezone name: " + timezoneFromServer); + + String canonicalTimezone = TimeUtil + .getCanoncialTimezone(timezoneFromServer, null); + System.out.println("Java timezone name: " + canonicalTimezone); + } + } finally { + if (rs != null) { + rs.close(); + } } } -} +} \ No newline at end of file Index: 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/VersionFSHierarchyMaker.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/VersionFSHierarchyMaker.java (.../VersionFSHierarchyMaker.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/com/mysql/jdbc/util/VersionFSHierarchyMaker.java (.../VersionFSHierarchyMaker.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,32 +1,32 @@ /* - Copyright (C) 2005-2006 MySQL AB + Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA + */ + package com.mysql.jdbc.util; import java.io.File; import java.io.FileOutputStream; import java.sql.Connection; import java.sql.ResultSet; -import java.util.Properties; import com.mysql.jdbc.NonRegisteringDriver; Index: 3rdParty_sources/mysql-connector/org/gjt/mm/mysql/Driver.java =================================================================== diff -u -r4e266757c429613d78b0fd2914d40d77a447daad -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/mysql-connector/org/gjt/mm/mysql/Driver.java (.../Driver.java) (revision 4e266757c429613d78b0fd2914d40d77a447daad) +++ 3rdParty_sources/mysql-connector/org/gjt/mm/mysql/Driver.java (.../Driver.java) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,27 +1,26 @@ /* - Copyright (C) 2002-2004 MySQL AB + Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. + The MySQL Connector/J is licensed under the terms of the GPLv2 + , like most MySQL Connectors. + There are special exceptions to the terms and conditions of the GPLv2 as it is applied to + this software, see the FLOSS License Exception + . - There are special exceptions to the terms and conditions of the GPL - as it is applied to this software. View the full text of the - exception in file EXCEPTIONS-CONNECTOR-J in the directory of this - software distribution. + This program is free software; you can redistribute it and/or modify it under the terms + of the GNU General Public License as published by the Free Software Foundation; version 2 + of the License. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along with this + program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth + Floor, Boston, MA 02110-1301 USA - - */ + package org.gjt.mm.mysql; import java.sql.SQLException; Index: 3rdParty_sources/versions.txt =================================================================== diff -u -r8e1ed196bfc1c28860729d8b0a23878bb3ecf1e7 -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- 3rdParty_sources/versions.txt (.../versions.txt) (revision 8e1ed196bfc1c28860729d8b0a23878bb3ecf1e7) +++ 3rdParty_sources/versions.txt (.../versions.txt) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -37,7 +37,7 @@ lucene 2.4.0 contains lucene-snowball 2.4.0 -MySQL Connector/J 5.0.8 +MySQL Connector/J 5.1.31 opensaml 2.6.0 Index: lams_build/3rdParty.userlibraries =================================================================== diff -u -r7e6defdc1696fa50c7d0fd0b02998bd5792f54de -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- lams_build/3rdParty.userlibraries (.../3rdParty.userlibraries) (revision 7e6defdc1696fa50c7d0fd0b02998bd5792f54de) +++ lams_build/3rdParty.userlibraries (.../3rdParty.userlibraries) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -1,6 +1,6 @@ - + @@ -22,7 +22,6 @@ - @@ -46,5 +45,6 @@ + Index: lams_build/conf/standalone.xml =================================================================== diff -u --- lams_build/conf/standalone.xml (revision 0) +++ lams_build/conf/standalone.xml (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + h2 + + sa + sa + + + + + @db.url.run@ + @db.driver@ + MySQL + utf8 + true + convertToNull + + + @db.location@ + false + false + 128K + 4 + 256K + 256K + 1M + 16K + 64K + 2K + + TRANSACTION_READ_COMMITTED + + 0 + 0 + 64 + false + false + FailingConnectionOnly + + + @db.username@ + @db.password@ + + + + false + false + false + + + 5 + 0 + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_build/lib/mysql/module.xml =================================================================== diff -u --- lams_build/lib/mysql/module.xml (revision 0) +++ lams_build/lib/mysql/module.xml (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -0,0 +1,32 @@ + + + + + + + + + + + + Index: lams_build/lib/mysql/mysql-connector-java-5.1.31-bin.jar =================================================================== diff -u Binary files differ Index: lams_build/liblist.txt =================================================================== diff -u -r7e6defdc1696fa50c7d0fd0b02998bd5792f54de -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- lams_build/liblist.txt (.../liblist.txt) (revision 7e6defdc1696fa50c7d0fd0b02998bd5792f54de) +++ lams_build/liblist.txt (.../liblist.txt) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -54,7 +54,7 @@ lucene lucene-core-2.4.0.jar 2.4.0 Apache License 2.0 Apache text search engine library lucene-snowball-2.4.0.jar 2.4.0 -mysql mysql-connector-java-5.0.8-bin.jar 5.0.8 GPL Oracle Java connector for MySQL +mysql mysql-connector-java-5.1.31-bin.jar 5.1.31 GPL Oracle Java connector for MySQL odmg odmg-3.0.jar 3.0 Index: lams_tool_deploy/.classpath =================================================================== diff -u -rd13588b3468e6d57bdf9944a19c4bbf479fb694f -r440668cd2f84fd819f07acf296c2c16f1a00b447 --- lams_tool_deploy/.classpath (.../.classpath) (revision d13588b3468e6d57bdf9944a19c4bbf479fb694f) +++ lams_tool_deploy/.classpath (.../.classpath) (revision 440668cd2f84fd819f07acf296c2c16f1a00b447) @@ -5,12 +5,12 @@ - +