/// <summary> /// Opens the physical connection to the server. /// </summary> /// <remarks>Usually called by the RequestConnector /// Method of the connection pool manager.</remarks> internal void Open() { ServerVersion = null; // If Connection.ConnectionString specifies a protocol version, we will // not try to fall back to version 2 on failure. _backendProtocolVersion = (settings.Protocol == ProtocolVersion.Unknown) ? ProtocolVersion.Version3 : settings.Protocol; // Reset state to initialize new connector in pool. CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this); try { // Establish protocol communication and handle authentication... CurrentState.Startup(this); } catch (NpgsqlException ne) { // Check for protocol not supported. If we have been told what protocol to use, // we will not try this step. if (settings.Protocol != ProtocolVersion.Unknown) { throw; } // If we attempted protocol version 3, it may be possible to drop back to version 2. if (BackendProtocolVersion != ProtocolVersion.Version3) { throw; } NpgsqlError Error0 = (NpgsqlError)ne.Errors[0]; // If NpgsqlError..ctor() encounters a version 2 error, // it will set its own protocol version to version 2. That way, we can tell // easily if the error was a FATAL: protocol error. if (Error0.BackendProtocolVersion != ProtocolVersion.Version2) { throw; } // Try using the 2.0 protocol. _mediator.ResetResponses(); BackendProtocolVersion = ProtocolVersion.Version2; CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this); // Establish protocol communication and handle authentication... CurrentState.Startup(this); } // Change the state of connection to open and ready. State = ConnectionState.Open; CurrentState = NpgsqlReadyState.Instance; // Fall back to the old way, SELECT VERSION(). // This should not happen for protocol version 3+. if (ServerVersion == null) { using (NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this)) { ServerVersion = new Version(PGUtil.ExtractServerVersion((string)command.ExecuteScalar())); } } StringBuilder sbInit = new StringBuilder(); // Adjust client encoding. NpgsqlParameterStatus clientEncodingParam = null; if (!ServerParameters.TryGetValue("client_encoding", out clientEncodingParam) || !string.Equals(clientEncodingParam.ParameterValue, "UTF8", StringComparison.OrdinalIgnoreCase) && !string.Equals(clientEncodingParam.ParameterValue, "UNICODE", StringComparison.OrdinalIgnoreCase)) { sbInit.AppendLine("SET CLIENT_ENCODING TO UTF8;"); } if (!string.IsNullOrEmpty(settings.SearchPath)) { // TODO: Add proper message when finding a semicolon in search_path. // This semicolon could lead to a sql injection security hole as someone could write in connection string: // searchpath=public;delete from table; and it would be executed. if (settings.SearchPath.Contains(";")) { throw new InvalidOperationException(); } sbInit.AppendLine("SET SEARCH_PATH=" + settings.SearchPath + ";"); } if (!string.IsNullOrEmpty(settings.ApplicationName)) { if (!SupportsApplicationName) { //TODO //throw new InvalidOperationException(resman.GetString("Exception_ApplicationNameNotSupported")); throw new InvalidOperationException("ApplicationName not supported."); } if (settings.ApplicationName.Contains(";")) { throw new InvalidOperationException(); } sbInit.AppendLine("SET APPLICATION_NAME='" + settings.ApplicationName.Replace('\'', '-') + "';"); } /* * Try to set SSL negotiation to 0. As of 2010-03-29, recent problems in SSL library implementations made * postgresql to add a parameter to set a value when to do this renegotiation or 0 to disable it. * Currently, Npgsql has a problem with renegotiation so, we are trying to disable it here. * This only works on postgresql servers where the ssl renegotiation settings is supported of course. * See http://lists.pgfoundry.org/pipermail/npgsql-devel/2010-February/001065.html for more information. */ sbInit.AppendLine("SET ssl_renegotiation_limit=0;"); /* * Set precision digits to maximum value possible. For postgresql before 9 it was 2, after that, it is 3. * This way, we set first to 2 and then to 3. If there is an error because of 3, it will have been set to 2 at least. * Check bug report #1010992 for more information. */ sbInit.AppendLine("SET extra_float_digits=3;"); try { new NpgsqlCommand(sbInit.ToString(), this).ExecuteBlind(); } catch { foreach (var line in sbInit.ToString().Split(Environment.NewLine.ToCharArray())) { try { if (line.Length > 0) { new NpgsqlCommand(line, this).ExecuteBlind(); } } catch { } } } // Make a shallow copy of the type mapping that the connector will own. // It is possible that the connector may add types to its private // mapping that will not be valid to another connector, even // if connected to the same backend version. _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone(); ProcessServerVersion(); // The connector is now fully initialized. Beyond this point, it is // safe to release it back to the pool rather than closing it. IsInitialized = true; }
/*/// <value>Counts the numbers of Connections that share * /// this Connector. Used in Release() to decide wether this * /// connector is to be moved to the PooledConnectors list.</value> * // internal int mShareCount;*/ /// <summary> /// Opens the physical connection to the server. /// </summary> /// <remarks>Usually called by the RequestConnector /// Method of the connection pool manager.</remarks> internal void Open() { ServerVersion = null; // If Connection.ConnectionString specifies a protocol version, we will // not try to fall back to version 2 on failure. _backendProtocolVersion = (settings.Protocol == ProtocolVersion.Unknown) ? ProtocolVersion.Version3 : settings.Protocol; // Reset state to initialize new connector in pool. CurrentState = NpgsqlClosedState.Instance; // Keep track of time remaining; Even though there may be multiple timeout-able calls, // this allows us to still respect the caller's timeout expectation. int connectTimeRemaining = this.ConnectionTimeout * 1000; DateTime attemptStart = DateTime.Now; // Get a raw connection, possibly SSL... CurrentState.Open(this, connectTimeRemaining); try { // Establish protocol communication and handle authentication... CurrentState.Startup(this); } catch (NpgsqlException ne) { connectTimeRemaining -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); // Check for protocol not supported. If we have been told what protocol to use, // we will not try this step. if (settings.Protocol != ProtocolVersion.Unknown) { throw; } // If we attempted protocol version 3, it may be possible to drop back to version 2. if (BackendProtocolVersion != ProtocolVersion.Version3) { throw; } NpgsqlError Error0 = (NpgsqlError)ne.Errors[0]; // If NpgsqlError..ctor() encounters a version 2 error, // it will set its own protocol version to version 2. That way, we can tell // easily if the error was a FATAL: protocol error. if (Error0.BackendProtocolVersion != ProtocolVersion.Version2) { throw; } // Try using the 2.0 protocol. _mediator.ResetResponses(); BackendProtocolVersion = ProtocolVersion.Version2; CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this, connectTimeRemaining); // Establish protocol communication and handle authentication... CurrentState.Startup(this); } // Change the state of connection to open and ready. _connection_state = ConnectionState.Open; CurrentState = NpgsqlReadyState.Instance; // Fall back to the old way, SELECT VERSION(). // This should not happen for protocol version 3+. if (ServerVersion == null) { //NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this); //ServerVersion = new Version(PGUtil.ExtractServerVersion((string) command.ExecuteScalar())); using (NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this)) { ServerVersion = new Version(PGUtil.ExtractServerVersion((string)command.ExecuteScalar())); } } // Adjust client encoding. NpgsqlParameterStatus clientEncodingParam = null; if ( !ServerParameters.TryGetValue("client_encoding", out clientEncodingParam) || (!string.Equals(clientEncodingParam.ParameterValue, "UTF8", StringComparison.OrdinalIgnoreCase) && !string.Equals(clientEncodingParam.ParameterValue, "UNICODE", StringComparison.OrdinalIgnoreCase)) ) { new NpgsqlCommand("SET CLIENT_ENCODING TO UTF8", this).ExecuteBlind(); } if (!string.IsNullOrEmpty(settings.SearchPath)) { /*NpgsqlParameter p = new NpgsqlParameter("p", DbType.String); * p.Value = settings.SearchPath; * NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH TO :p,public", this); * commandSearchPath.Parameters.Add(p); * commandSearchPath.ExecuteNonQuery();*/ /*NpgsqlParameter p = new NpgsqlParameter("p", DbType.String); * p.Value = settings.SearchPath; * NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH TO :p,public", this); * commandSearchPath.Parameters.Add(p); * commandSearchPath.ExecuteNonQuery();*/ // TODO: Add proper message when finding a semicolon in search_path. // This semicolon could lead to a sql injection security hole as someone could write in connection string: // searchpath=public;delete from table; and it would be executed. if (settings.SearchPath.Contains(";")) { throw new InvalidOperationException(); } // This is using string concatenation because set search_path doesn't allow type casting. ::text NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH=" + settings.SearchPath, this); commandSearchPath.ExecuteBlind(); } if (!string.IsNullOrEmpty(settings.ApplicationName)) { if (!SupportsApplicationName) { //TODO //throw new InvalidOperationException(resman.GetString("Exception_ApplicationNameNotSupported")); throw new InvalidOperationException("ApplicationName not supported."); } if (settings.ApplicationName.Contains(";")) { throw new InvalidOperationException(); } NpgsqlCommand commandApplicationName = new NpgsqlCommand("SET APPLICATION_NAME='" + settings.ApplicationName + "'", this); commandApplicationName.ExecuteBlind(); } /* * Try to set SSL negotiation to 0. As of 2010-03-29, recent problems in SSL library implementations made * postgresql to add a parameter to set a value when to do this renegotiation or 0 to disable it. * Currently, Npgsql has a problem with renegotiation so, we are trying to disable it here. * This only works on postgresql servers where the ssl renegotiation settings is supported of course. * See http://lists.pgfoundry.org/pipermail/npgsql-devel/2010-February/001065.html for more information. */ try { NpgsqlCommand commandSslrenegotiation = new NpgsqlCommand("SET ssl_renegotiation_limit=0", this); commandSslrenegotiation.ExecuteBlind(); } catch {} /* * Set precision digits to maximum value possible. For postgresql before 9 it was 2, after that, it is 3. * This way, we set first to 2 and then to 3. If there is an error because of 3, it will have been set to 2 at least. * Check bug report #1010992 for more information. */ try { NpgsqlCommand commandSingleDoublePrecision = new NpgsqlCommand("SET extra_float_digits=2;SET extra_float_digits=3;", this); commandSingleDoublePrecision.ExecuteBlind(); } catch {} /* * Set lc_monetary format to 'C' ir order to get a culture agnostic representation of money. * I noticed that on Windows, even when the lc_monetary is English_United States.UTF-8, negative * money is formatted as ($value) with parentheses to indicate negative value. * By going with a culture agnostic format, we get a consistent behavior. */ try { NpgsqlCommand commandMonetaryFormatC = new NpgsqlCommand("SET lc_monetary='C';", this); commandMonetaryFormatC.ExecuteBlind(); } catch { } // Make a shallow copy of the type mapping that the connector will own. // It is possible that the connector may add types to its private // mapping that will not be valid to another connector, even // if connected to the same backend version. _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone(); ProcessServerVersion(); // The connector is now fully initialized. Beyond this point, it is // safe to release it back to the pool rather than closing it. IsInitialized = true; }
/*/// <value>Counts the numbers of Connections that share * /// this Connector. Used in Release() to decide wether this * /// connector is to be moved to the PooledConnectors list.</value> * // internal int mShareCount;*/ /// <summary> /// Opens the physical connection to the server. /// </summary> /// <remarks>Usually called by the RequestConnector /// Method of the connection pool manager.</remarks> internal void Open() { ServerVersion = null; // If Connection.ConnectionString specifies a protocol version, we will // not try to fall back to version 2 on failure. _backendProtocolVersion = (settings.Protocol == ProtocolVersion.Unknown) ? ProtocolVersion.Version3 : settings.Protocol; // Reset state to initialize new connector in pool. CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this); try { // Establish protocol communication and handle authentication... CurrentState.Startup(this); } catch (NpgsqlException ne) { // Check for protocol not supported. If we have been told what protocol to use, // we will not try this step. if (settings.Protocol != ProtocolVersion.Unknown) { throw; } // If we attempted protocol version 3, it may be possible to drop back to version 2. if (BackendProtocolVersion != ProtocolVersion.Version3) { throw; } NpgsqlError Error0 = (NpgsqlError)ne.Errors[0]; // If NpgsqlError..ctor() encounters a version 2 error, // it will set its own protocol version to version 2. That way, we can tell // easily if the error was a FATAL: protocol error. if (Error0.BackendProtocolVersion != ProtocolVersion.Version2) { throw; } // Try using the 2.0 protocol. _mediator.ResetResponses(); BackendProtocolVersion = ProtocolVersion.Version2; CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this); // Establish protocol communication and handle authentication... CurrentState.Startup(this); } // Change the state of connection to open and ready. _connection_state = ConnectionState.Open; CurrentState = NpgsqlReadyState.Instance; // Fall back to the old way, SELECT VERSION(). // This should not happen for protocol version 3+. if (ServerVersion == null) { NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this); ServerVersion = new Version(PGUtil.ExtractServerVersion((string)command.ExecuteScalar())); } // Adjust client encoding. NpgsqlParameterStatus clientEncodingParam = null; if ( !ServerParameters.TryGetValue("client_encoding", out clientEncodingParam) || (!string.Equals(clientEncodingParam.ParameterValue, "UTF8", StringComparison.OrdinalIgnoreCase) && !string.Equals(clientEncodingParam.ParameterValue, "UNICODE", StringComparison.OrdinalIgnoreCase)) ) { new NpgsqlCommand("SET CLIENT_ENCODING TO UTF8", this).ExecuteBlind(); } if (!string.IsNullOrEmpty(settings.SearchPath)) { /*NpgsqlParameter p = new NpgsqlParameter("p", DbType.String); * p.Value = settings.SearchPath; * NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH TO :p,public", this); * commandSearchPath.Parameters.Add(p); * commandSearchPath.ExecuteNonQuery();*/ /*NpgsqlParameter p = new NpgsqlParameter("p", DbType.String); * p.Value = settings.SearchPath; * NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH TO :p,public", this); * commandSearchPath.Parameters.Add(p); * commandSearchPath.ExecuteNonQuery();*/ // TODO: Add proper message when finding a semicolon in search_path. // This semicolon could lead to a sql injection security hole as someone could write in connection string: // searchpath=public;delete from table; and it would be executed. if (settings.SearchPath.Contains(";")) { throw new InvalidOperationException(); } // This is using string concatenation because set search_path doesn't allow type casting. ::text NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH=" + settings.SearchPath, this); commandSearchPath.ExecuteBlind(); } /* * Try to set SSL negotiation to 0. As of 2010-03-29, recent problems in SSL library implementations made * postgresql to add a parameter to set a value when to do this renegotiation or 0 to disable it. * Currently, Npgsql has a problem with renegotiation so, we are trying to disable it here. * This only works on postgresql servers where the ssl renegotiation settings is supported of course. * See http://lists.pgfoundry.org/pipermail/npgsql-devel/2010-February/001065.html for more information. */ try { NpgsqlCommand commandSslrenegotiation = new NpgsqlCommand("SET ssl_renegotiation_limit=0", this); commandSslrenegotiation.ExecuteBlind(); } catch {} // Make a shallow copy of the type mapping that the connector will own. // It is possible that the connector may add types to its private // mapping that will not be valid to another connector, even // if connected to the same backend version. _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone(); ProcessServerVersion(); // The connector is now fully initialized. Beyond this point, it is // safe to release it back to the pool rather than closing it. IsInitialized = true; }