All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.snowflake.client.jdbc.SnowflakeDriver Maven / Gradle / Ivy

There is a newer version: 3.21.0
Show newest version
/*
 * Copyright (c) 2012-2019 Snowflake Computing Inc. All rights reserved.
 */

package net.snowflake.client.jdbc;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.List;
import java.util.Properties;
import net.snowflake.client.config.ConnectionParameters;
import net.snowflake.client.config.SFConnectionConfigParser;
import net.snowflake.client.core.SecurityUtil;
import net.snowflake.client.core.SnowflakeJdbcInternalApi;
import net.snowflake.client.jdbc.telemetryOOB.TelemetryService;
import net.snowflake.client.log.SFLogger;
import net.snowflake.client.log.SFLoggerFactory;
import net.snowflake.common.core.ResourceBundleManager;
import net.snowflake.common.core.SqlState;

/**
 * JDBC Driver implementation of Snowflake for production. To use this driver, specify the following
 * URL: jdbc:snowflake://host:port
 *
 * 

Note: don't add logger to this class since logger init will potentially break driver class * loading */ public class SnowflakeDriver implements Driver { private static final SFLogger logger = SFLoggerFactory.getLogger(SnowflakeDriver.class); public static final String AUTO_CONNECTION_STRING_PREFIX = "jdbc:snowflake:auto"; static SnowflakeDriver INSTANCE; public static final Properties EMPTY_PROPERTIES = new Properties(); public static String implementVersion = "3.19.1"; static int majorVersion = 0; static int minorVersion = 0; static long patchVersion = 0; protected static boolean disableIncidents = false; private static boolean disableArrowResultFormat = false; private static String disableArrowResultFormatMessage; private static final ResourceBundleManager versionResourceBundleManager = ResourceBundleManager.getSingleton("net.snowflake.client.jdbc.version"); static { try { DriverManager.registerDriver(INSTANCE = new SnowflakeDriver()); } catch (SQLException ex) { throw new IllegalStateException("Unable to register " + SnowflakeDriver.class.getName(), ex); } initializeArrowSupport(); /* * Get the manifest properties here. */ initializeClientVersionFromManifest(); SecurityUtil.addBouncyCastleProvider(); // Telemetry OOB is disabled TelemetryService.disableOOBTelemetry(); } /** try to initialize Arrow support if fails, JDBC is going to use the legacy format */ private static void initializeArrowSupport() { try { // this is required to enable direct memory usage for Arrow buffers in Java System.setProperty("io.netty.tryReflectionSetAccessible", "true"); } catch (Throwable t) { // fail to enable required feature for Arrow disableArrowResultFormat = true; disableArrowResultFormatMessage = t.getLocalizedMessage(); } if ("true" .equals(SnowflakeUtil.systemGetProperty("snowflake.jdbc.enable.illegalAccessWarning"))) { return; } disableIllegalReflectiveAccessWarning(); } static void disableIllegalReflectiveAccessWarning() { // The netty dependency of arrow will cause an illegal reflective access warning // This function try to eliminate the warning by setting // jdk.internal.module.IllegalAccessLogger's logger as null // Disable this function and manually run arrow tests, e.g. testResultSetMetadata., then // the warning can be found in output. try { Class unsafeClass = Class.forName("sun.misc.Unsafe"); Field field = unsafeClass.getDeclaredField("theUnsafe"); field.setAccessible(true); Object unsafe = field.get(null); Method putObjectVolatile = unsafeClass.getDeclaredMethod( "putObjectVolatile", Object.class, long.class, Object.class); Method staticFieldOffset = unsafeClass.getDeclaredMethod("staticFieldOffset", Field.class); Method staticFieldBase = unsafeClass.getDeclaredMethod("staticFieldBase", Field.class); Class loggerClass = Class.forName("jdk.internal.module.IllegalAccessLogger"); Field loggerField = loggerClass.getDeclaredField("logger"); Long loggerOffset = (Long) staticFieldOffset.invoke(unsafe, loggerField); Object loggerBase = staticFieldBase.invoke(unsafe, loggerField); putObjectVolatile.invoke(unsafe, loggerBase, loggerOffset, null); } catch (Throwable ex) { // If failed to eliminate warnings, do nothing } } private static void initializeClientVersionFromManifest() { /* * Get JDBC version numbers from static string in snowflake-jdbc */ try { // parse implementation version major.minor.change if (implementVersion != null) { String[] versionBreakdown = implementVersion.split("\\."); if (versionBreakdown.length == 3) { majorVersion = Integer.parseInt(versionBreakdown[0]); minorVersion = Integer.parseInt(versionBreakdown[1]); patchVersion = Long.parseLong(versionBreakdown[2]); } else { throw new SnowflakeSQLLoggedException( null, ErrorCode.INTERNAL_ERROR.getMessageCode(), SqlState.INTERNAL_ERROR, /*session = */ "Invalid Snowflake JDBC Version: " + implementVersion); } } else { throw new SnowflakeSQLException( SqlState.INTERNAL_ERROR, ErrorCode.INTERNAL_ERROR.getMessageCode(), /*session = */ null, "Snowflake JDBC Version is not set. " + "Ensure static version string was initialized."); } } catch (Throwable ex) { } } /** * For testing purposes only- used to compare that JDBC version in pom.xml matches static string * * @return String with version from pom.xml file */ static String getClientVersionStringFromManifest() { return versionResourceBundleManager.getLocalizedMessage("version"); } public static boolean isDisableArrowResultFormat() { return disableArrowResultFormat; } public static String getDisableArrowResultFormatMessage() { return disableArrowResultFormatMessage; } /** * Utility method to verify if the standard or fips snowflake-jdbc driver is being used. * * @return */ public static String getImplementationTitle() { Package pkg = Package.getPackage("net.snowflake.client.jdbc"); return pkg.getImplementationTitle(); } /** * Utility method to get the complete jar name with version. * * @return */ public static String getJdbcJarname() { return String.format("%s-%s", getImplementationTitle(), implementVersion); } /** * Checks whether a given url is in a valid format. * *

The current uri format is: jdbc:snowflake://[host[:port]] * *

jdbc:snowflake:// - run in embedded mode jdbc:snowflake://localhost - connect to localhost * default port (8080) * *

jdbc:snowflake://localhost:8080- connect to localhost port 8080 * * @param url url of the database including host and port * @return true if the url is valid */ @Override public boolean acceptsURL(String url) { return SnowflakeConnectString.parse(url, EMPTY_PROPERTIES).isValid(); } /** * Connect method * * @param url jdbc url * @param info addition info for passing database/schema names * @return connection * @throws SQLException if failed to create a snowflake connection */ @Override public Connection connect(String url, Properties info) throws SQLException { ConnectionParameters connectionParameters = overrideByFileConnectionParametersIfAutoConfiguration(url, info); if (connectionParameters.getUrl() == null) { // expected return format per the JDBC spec for java.sql.Driver#connect() throw new SnowflakeSQLException("Unable to connect to url of 'null'."); } if (!SnowflakeConnectString.hasSupportedPrefix(connectionParameters.getUrl())) { return null; // expected return format per the JDBC spec for java.sql.Driver#connect() } SnowflakeConnectString conStr = SnowflakeConnectString.parse( connectionParameters.getUrl(), connectionParameters.getParams()); if (!conStr.isValid()) { throw new SnowflakeSQLException("Connection string is invalid. Unable to parse."); } return new SnowflakeConnectionV1( connectionParameters.getUrl(), connectionParameters.getParams()); } private static ConnectionParameters overrideByFileConnectionParametersIfAutoConfiguration( String url, Properties info) throws SnowflakeSQLException { if (url != null && url.contains(AUTO_CONNECTION_STRING_PREFIX)) { // Connect using connection configuration file ConnectionParameters connectionParameters = SFConnectionConfigParser.buildConnectionParameters(); if (connectionParameters == null) { throw new SnowflakeSQLException( "Unavailable connection configuration parameters expected for auto configuration using file"); } return connectionParameters; } else { return new ConnectionParameters(url, info); } } /** * Connect method using connection configuration file * * @return connection * @throws SQLException if failed to create a snowflake connection */ @SnowflakeJdbcInternalApi public Connection connect() throws SQLException { logger.debug("Execute internal method connect() without parameters"); return connect(AUTO_CONNECTION_STRING_PREFIX, null); } @Override public int getMajorVersion() { return majorVersion; } @Override public int getMinorVersion() { return minorVersion; } @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { DriverPropertyInfo[] retVal; if (url == null || url.isEmpty()) { retVal = new DriverPropertyInfo[1]; retVal[0] = new DriverPropertyInfo("serverURL", null); retVal[0].description = "server URL in form of ://:/"; return retVal; } Connection con = new SnowflakeConnectionV1(url, info, true); List missingProperties = ((SnowflakeConnectionV1) con).returnMissingProperties(); con.close(); retVal = new DriverPropertyInfo[missingProperties.size()]; retVal = missingProperties.toArray(retVal); return retVal; } @Override public boolean jdbcCompliant() { return false; } @Override public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } public static boolean isDisableIncidents() { return disableIncidents; } public static void setDisableIncidents(boolean throttleIncidents) { SnowflakeDriver.disableIncidents = throttleIncidents; } public static final void main(String[] args) { if (args.length > 0 && "--version".equals(args[0])) { Package pkg = Package.getPackage("net.snowflake.client.jdbc"); if (pkg != null) { System.out.println(pkg.getImplementationVersion()); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy