16 package ai.heavy.jdbc;
20 import org.apache.thrift.TException;
21 import org.apache.thrift.protocol.TBinaryProtocol;
22 import org.apache.thrift.protocol.TJSONProtocol;
23 import org.apache.thrift.protocol.TProtocol;
24 import org.apache.thrift.transport.TTransport;
25 import org.apache.thrift.transport.TTransportException;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 import java.security.*;
31 import java.security.cert.X509Certificate;
32 import java.sql.Array;
34 import java.sql.CallableStatement;
36 import java.sql.Connection;
37 import java.sql.DatabaseMetaData;
38 import java.sql.NClob;
39 import java.sql.PreparedStatement;
40 import java.sql.SQLClientInfoException;
41 import java.sql.SQLException;
42 import java.sql.SQLWarning;
43 import java.sql.SQLXML;
44 import java.sql.Savepoint;
45 import java.sql.Statement;
46 import java.sql.Struct;
48 import java.util.concurrent.Executor;
50 import javax.crypto.Cipher;
52 import ai.heavy.thrift.server.Heavy;
53 import ai.heavy.thrift.server.TDBException;
54 import ai.heavy.thrift.server.TDatumType;
55 import ai.heavy.thrift.server.TServerStatus;
56 import sun.security.provider.X509Factory;
64 public static String
getX509(X509Certificate cert)
throws Exception {
65 String encoded = Base64.getMimeEncoder().encodeToString(cert.getEncoded());
67 encoded = X509Factory.BEGIN_CERT +
"\n" + encoded +
"\n" + X509Factory.END_CERT;
75 KeyStore keystore = KeyStore.getInstance(
"PKCS12");
76 java.io.FileInputStream fis =
new java.io.FileInputStream(
filename);
77 keystore.load(fis, password.toCharArray());
79 Enumeration<String> eE = keystore.aliases();
81 while (eE.hasMoreElements()) {
82 alias = eE.nextElement();
86 throw new SQLException(
"pkcs12 file [" +
filename
87 +
"] contains an incorrect number [" + count
88 +
"] of certificate(s); only a single certificate is allowed");
91 X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
93 s_struct.key = keystore.getKey(alias, password.toCharArray());
94 }
catch (Exception eX) {
95 HeavyAIConnection.logger.error(eX.getMessage());
139 final static Logger
logger = LoggerFactory.getLogger(HeavyAIConnection.class);
142 Arrays.asList(
"binary",
"binary_tls",
"http",
"https",
"https_insecure"));
173 String connection_url, Properties query_props)
throws SQLException {
182 String[] url_components = connection_url.split(
"\\?");
183 if (url_components.length == 2) {
186 StringReader reader =
new StringReader(url_components[1].replace(
'&',
'\n'));
188 query_props.load(reader);
189 }
catch (IOException iex) {
190 throw new SQLException(iex.toString());
192 }
else if (url_components.length > 2) {
193 throw new SQLException(
194 "Invalid connection string. Multiple query components included ["
195 + connection_url +
"]");
198 return url_components[0];
202 throws SQLException {
204 String[] url_values = connection_url.split(
":");
210 throw new SQLException(
"Invalid number of arguments provided in url ["
211 + url_values.length +
"]. Maximum allowed ["
214 for (
int i = 2; i < url_values.length; i++) {
218 if (existingValue != null && !existingValue.equals((url_values[i]))) {
219 logger.warn(
"Connection property [" + Options.option_order[i - 2]
220 +
"] has been provided with different values in the URL and query component of the url. Defaulting to the URL value");
225 for (String key : baseProperties.stringPropertyNames()) {
226 String existingValue = getProperty(key);
227 if (existingValue != null
228 && !existingValue.equals(baseProperties.getProperty(key))) {
229 logger.warn(
"Connection property " + key
230 +
"] has been provided with different values in the properties object and the url. Defaulting to the URL value");
232 setProperty(key, baseProperties.getProperty(key));
241 for (String key : this.stringPropertyNames()) {
244 logger.warn(
"Unsupported configuration key" + key +
" used.");
250 if (hN.startsWith(
"//")) {
256 String protocol =
"binary";
259 protocol.toLowerCase();
261 logger.warn(
"Incorrect protcol [" + protocol
262 +
"] supplied. Possible values are [" + protocol_set.toString()
263 +
"]. Using binary as default");
272 }
catch (NumberFormatException nfe) {
273 throw new SQLException(
280 logger.warn(
"server trust store ["
282 +
" specfied without a password");
286 logger.warn(
"server trust store password specified without a keystore file");
293 }
catch (NumberFormatException nfe) {
294 throw new SQLException(
295 "Invalid value supplied for max rows " + getProperty(
Options.
max_rows));
345 logger.debug(
"HeavyAIConnection clone");
349 }
catch (CloneNotSupportedException eE) {
350 throw new SQLException(
356 TProtocol protocol = dbConnection.manageConnection();
357 dbConnection.client =
new Heavy.Client(protocol);
358 }
catch (java.lang.Exception jE) {
359 throw new SQLException(
"Error creating new connection "
370 String trust_store = null;
375 String trust_store_pwd = null;
381 TProtocol protocol = null;
384 skT = SockTransportProperties.getUnencryptedClient();
389 protocol =
new TJSONProtocol(transport);
392 skT = SockTransportProperties.getUnencryptedClient();
395 if (!transport.isOpen()) transport.open();
396 protocol =
new TBinaryProtocol(transport);
399 if (trust_store == null) {
400 skT = SockTransportProperties.getEncryptedClientDefaultTrustStore(
401 !this.cP.isHttpsProtocol_insecure());
403 skT = SockTransportProperties.getEncryptedClientSpecifiedTrustStore(
404 trust_store, trust_store_pwd, !this.cP.isHttpsProtocol_insecure());
412 if (trust_store == null) {
413 skT = SockTransportProperties.getEncryptedClientDefaultTrustStore(
false);
415 skT = SockTransportProperties.getEncryptedClientSpecifiedTrustStore(
416 trust_store, trust_store_pwd,
false);
422 protocol =
new TBinaryProtocol(
transport);
424 throw new SQLException(
"Invalid protocol supplied");
429 private void setSession(Object pki_auth)
throws java.lang.Exception {
430 KeyLoader.S_struct s_struct = null;
432 if (pki_auth != null && pki_auth.toString().equalsIgnoreCase(
"true")) {
433 s_struct = KeyLoader.getDetails_pkcs12(this.cP.getProperty(
Options.sslcert),
444 if (pki_auth != null && pki_auth.toString().equalsIgnoreCase(
"true")) {
445 Cipher cipher = Cipher.getInstance(s_struct.key.getAlgorithm());
446 cipher.init(Cipher.DECRYPT_MODE, s_struct.key);
448 byte[] decodedBytes = Base64.getDecoder().decode(
session);
449 byte[] decoded_bytes = cipher.doFinal(decodedBytes);
450 session =
new String(decoded_bytes,
"UTF-8");
459 client =
new Heavy.Client(protocol);
462 }
catch (TTransportException ex) {
463 throw new SQLException(
"Thrift transport connection failed - "
466 }
catch (TDBException ex) {
467 throw new SQLException(
"HEAVY.AI connection failed - "
470 }
catch (TException ex) {
471 throw new SQLException(
473 }
catch (java.lang.Exception ex) {
474 throw new SQLException(
486 throws SQLException {
492 throws SQLException {
493 throw new UnsupportedOperationException(
"Not supported yet,"
494 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
495 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
496 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
500 public String
nativeSQL(String sql)
throws SQLException {
501 throw new UnsupportedOperationException(
"Not supported yet,"
502 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
503 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
504 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
509 throws SQLException {
519 public void commit() throws SQLException {
525 throw new UnsupportedOperationException(
"Not supported yet,"
526 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
527 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
528 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
532 public void close() throws SQLException {
534 logger.debug(
"Session at close is " +
session);
539 }
catch (TDBException ex) {
540 throw new SQLException(
"disconnect failed." + ex.getError_msg());
541 }
catch (TException ex) {
542 throw new SQLException(
"disconnect failed." + ex.toString());
569 throws SQLException {
578 TServerStatus server_status = client.get_server_status(
session);
579 return server_status.read_only;
581 }
catch (TDBException ex) {
582 throw new SQLException(
583 "get_server_status failed during isReadOnly check." + ex.getError_msg());
584 }
catch (TException ex) {
585 throw new SQLException(
586 "get_server_status failed during isReadOnly check." + ex.toString());
594 throw new UnsupportedOperationException(
"Not supported yet,"
595 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
596 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
597 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
607 throws SQLException {
612 return Connection.TRANSACTION_NONE;
627 throws SQLException {
633 String sql,
int resultSetType,
int resultSetConcurrency)
634 throws SQLException {
640 String sql,
int resultSetType,
int resultSetConcurrency)
641 throws SQLException {
642 throw new UnsupportedOperationException(
"Not supported yet,"
643 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
644 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
645 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
650 throws SQLException {
651 throw new UnsupportedOperationException(
"Not supported yet,"
652 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
653 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
654 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
659 throws SQLException {
660 throw new UnsupportedOperationException(
"Not supported yet,"
661 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
662 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
663 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
668 throws SQLException {
669 throw new UnsupportedOperationException(
"Not supported yet,"
670 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
671 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
672 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
677 throw new UnsupportedOperationException(
"Not supported yet,"
678 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
679 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
680 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
685 throw new UnsupportedOperationException(
"Not supported yet,"
686 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
687 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
688 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
693 throws SQLException {
694 throw new UnsupportedOperationException(
"Not supported yet,"
695 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
696 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
697 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
702 throws SQLException {
703 throw new UnsupportedOperationException(
"Not supported yet,"
704 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
705 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
706 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
711 throws SQLException {
712 throw new UnsupportedOperationException(
"Not supported yet,"
713 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
714 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
715 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
720 int resultSetType,
int resultSetConcurrency,
int resultSetHoldability)
721 throws SQLException {
722 throw new UnsupportedOperationException(
"Not supported yet,"
723 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
724 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
725 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
731 int resultSetConcurrency,
732 int resultSetHoldability)
throws SQLException {
733 throw new UnsupportedOperationException(
"Not supported yet,"
734 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
735 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
736 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
742 int resultSetConcurrency,
743 int resultSetHoldability)
throws SQLException {
744 throw new UnsupportedOperationException(
"Not supported yet,"
745 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
746 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
747 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
752 throws SQLException {
753 throw new UnsupportedOperationException(
"Not supported yet,"
754 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
755 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
756 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
761 throws SQLException {
762 throw new UnsupportedOperationException(
"Not supported yet,"
763 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
764 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
765 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
770 throws SQLException {
771 throw new UnsupportedOperationException(
"Not supported yet,"
772 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
773 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
774 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
779 throw new UnsupportedOperationException(
"Not supported yet,"
780 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
781 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
782 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
787 throw new UnsupportedOperationException(
"Not supported yet,"
788 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
789 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
790 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
795 throw new UnsupportedOperationException(
"Not supported yet,"
796 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
797 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
798 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
803 throw new UnsupportedOperationException(
"Not supported yet,"
804 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
805 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
806 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
810 public boolean isValid(
int timeout)
throws SQLException {
812 client.get_server_status(
session);
813 }
catch (TTransportException ex) {
814 throw new SQLException(
"Connection failed - " + ex.toString());
815 }
catch (TDBException ex) {
816 throw new SQLException(
"Connection failed - " + ex.getError_msg());
817 }
catch (TException ex) {
818 throw new SQLException(
"Connection failed - " + ex.toString());
825 throw new UnsupportedOperationException(
"Not supported yet,"
826 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
827 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
828 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
832 public void setClientInfo(Properties properties)
throws SQLClientInfoException {
833 throw new UnsupportedOperationException(
"Not supported yet,"
834 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
835 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
836 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
841 throws SQLException {
842 throw new UnsupportedOperationException(
"Not supported yet,"
843 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
844 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
845 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
850 throw new UnsupportedOperationException(
"Not supported yet,"
851 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
852 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
853 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
858 throws SQLException {
861 type = TDatumType.valueOf(typeName.toUpperCase());
862 }
catch (IllegalArgumentException ex) {
863 throw new SQLException(
"No matching heavyDB type for " +
typeName);
870 throws SQLException {
871 throw new UnsupportedOperationException(
"Not supported yet,"
872 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
873 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
874 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
878 public void setSchema(String schema)
throws SQLException {
882 if (db_name == null) {
883 throw new SQLException(
"db name not set, "
884 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
885 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
886 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
888 if (!schema.equals(db_name.toString())) {
889 logger.warn(
"Connected to schema [" + schema +
"] differs from db name [" + db_name
897 throw new UnsupportedOperationException(
"Not supported yet,"
898 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
899 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
900 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
904 public void abort(Executor executor)
throws SQLException {
905 throw new UnsupportedOperationException(
"Not supported yet,"
906 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
907 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
908 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
913 throws SQLException {
914 throw new UnsupportedOperationException(
"Not supported yet,"
915 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
916 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
917 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
922 throw new UnsupportedOperationException(
"Not supported yet,"
923 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
924 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
925 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
929 public <T>
T unwrap(Class<T> iface)
throws SQLException {
930 throw new UnsupportedOperationException(
"Not supported yet,"
931 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
932 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
933 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
938 throws SQLException {
939 throw new UnsupportedOperationException(
"Not supported yet,"
940 +
" line:" +
new Throwable().getStackTrace()[0].getLineNumber()
941 +
" class:" +
new Throwable().getStackTrace()[0].getClassName()
942 +
" method:" +
new Throwable().getStackTrace()[0].getMethodName());
DatabaseMetaData getMetaData()
static S_struct getDetails_pkcs12(String filename, String password)
void setAutoCommit(boolean autoCommit)
HeavyAIConnection getAlternateConnection()
static String server_trust_store_pwd
Set< String > protocol_set
boolean isHttpsProtocol_insecure()
static String getX509(X509Certificate cert)
Struct createStruct(String typeName, Object[] attributes)
void setCatalog(String catalog)
static final Logger logger
boolean containsTrustStore()
void abort(Executor executor)
void setHoldability(int holdability)
void setClientInfo(Properties properties)
void setReadOnly(boolean readOnly)
Map< String, Class<?> > getTypeMap()
TProtocol manageConnection()
static String server_trust_store
HeavyAIConnection(String url, Properties base_properties)
Array createArrayOf(String typeName, Object[] elements)
PreparedStatement prepareStatement(String sql, String[] columnNames)
Connection_properties(String connection_url, Properties baseProperties)
PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
boolean isWrapperFor(Class<?> iface)
Statement createStatement(int resultSetType, int resultSetConcurrency)
void setSession(Object pki_auth)
PreparedStatement prepareStatement(String sql)
PreparedStatement prepareStatement(String sql, int[] columnIndexes)
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
void setTransactionIsolation(int level)
String extract_and_remove_query_components(String connection_url, Properties query_props)
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
static String getExceptionDetail(Exception ex)
boolean isValid(int timeout)
static String sslkey_password
void rollback(Savepoint savepoint)
static String[] option_order
void setClientInfo(String name, String value)
Savepoint setSavepoint(String name)
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
Properties getClientInfo()
void setTypeMap(Map< String, Class<?>> map)
int getTransactionIsolation()
void setSchema(String schema)
std::string typeName(const T *v)
Statement createStatement()
std::string filename(char const *path)
String nativeSQL(String sql)
void setNetworkTimeout(Executor executor, int milliseconds)
public< T > T unwrap(Class< T > iface)
Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
String getClientInfo(String name)
boolean isHttpsProtocol()
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
void releaseSavepoint(Savepoint savepoint)
CallableStatement prepareCall(String sql)