internal NpgsqlError(ProtocolVersion protocolVersion, Stream stream) { switch (protocol_version = protocolVersion) { case ProtocolVersion.Version2: string[] parts = PGUtil.ReadString(stream).Split(new char[] { ':' }, 2); if (parts.Length == 2) { _severity = parts[0].Trim(); _message = parts[1].Trim(); } else { _severity = string.Empty; _message = parts[0].Trim(); } break; case ProtocolVersion.Version3: // Check the messageLength value. If it is 1178686529, this would be the // "FATA" string, which would mean a protocol 2.0 error string. if (PGUtil.ReadInt32(stream) == 1178686529) { string[] v2Parts = ("FATA" + PGUtil.ReadString(stream)).Split(new char[] { ':' }, 2); if (v2Parts.Length == 2) { _severity = v2Parts[0].Trim(); _message = v2Parts[1].Trim(); } else { _severity = string.Empty; _message = v2Parts[0].Trim(); } protocol_version = ProtocolVersion.Version2; } else { for (char field = (char)stream.ReadByte(); field != 0; field = (char)stream.ReadByte()) { switch (field) { case 'S': _severity = PGUtil.ReadString(stream); break; case 'C': _code = PGUtil.ReadString(stream); break; case 'M': _message = PGUtil.ReadString(stream); break; case 'D': _detail = PGUtil.ReadString(stream); break; case 'H': _hint = PGUtil.ReadString(stream); break; case 'P': _position = PGUtil.ReadString(stream); break; case 'p': _internalPosition = PGUtil.ReadString(stream); break; case 'q': _internalQuery = PGUtil.ReadString(stream); break; case 'W': _where = PGUtil.ReadString(stream); break; case 'F': _file = PGUtil.ReadString(stream); break; case 'L': _line = PGUtil.ReadString(stream); break; case 'R': _routine = PGUtil.ReadString(stream); break; case 's': _schemaName = PGUtil.ReadString(stream); break; case 't': _tableName = PGUtil.ReadString(stream); break; case 'c': _columnName = PGUtil.ReadString(stream); break; case 'd': _datatypeName = PGUtil.ReadString(stream); break; case 'n': _constraintName = PGUtil.ReadString(stream); break; default: // Unknown error field; consume and discard. PGUtil.ReadString(stream); break; } } } break; } }
internal NpgsqlError(ProtocolVersion protocolVersion, String errorMessage) { protocol_version = protocolVersion; _message = errorMessage; }
public NpgsqlQuery(NpgsqlCommand command, ProtocolVersion protocolVersion) { _command = command; _protocolVersion = protocolVersion; }
internal NpgsqlError(ProtocolVersion protocolVersion, Stream stream) { switch (protocol_version = protocolVersion) { case ProtocolVersion.Version2: string[] parts = PGUtil.ReadString(stream).Split(new char[] { ':' }, 2); if (parts.Length == 2) { _severity = parts[0].Trim(); _message = parts[1].Trim(); } else { _severity = string.Empty; _message = parts[0].Trim(); } break; case ProtocolVersion.Version3: // Check the messageLength value. If it is 1178686529, this would be the // "FATA" string, which would mean a protocol 2.0 error string. if (PGUtil.ReadInt32(stream) == 1178686529) { string[] v2Parts = ("FATA" + PGUtil.ReadString(stream)).Split(new char[] { ':' }, 2); if (v2Parts.Length == 2) { _severity = v2Parts[0].Trim(); _message = v2Parts[1].Trim(); } else { _severity = string.Empty; _message = v2Parts[0].Trim(); } protocol_version = ProtocolVersion.Version2; } else { bool done = false; int fieldCode; while (!done && (fieldCode = stream.ReadByte()) != -1) { switch ((byte)fieldCode) { case 0: // Null terminator; error message fully consumed. done = true; ; break; case (byte)ErrorFieldTypeCodes.Severity: _severity = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Code: _code = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Message: _message = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Detail: _detail = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Hint: _hint = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Position: _position = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.InternalPosition: _internalPosition = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.InternalQuery: _internalQuery = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Where: _where = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.File: _file = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Line: _line = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.Routine: _routine = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.SchemaName: _schemaName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.TableName: _tableName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.ColumnName: _columnName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.DataTypeName: _datatypeName = PGUtil.ReadString(stream); ; break; case (byte)ErrorFieldTypeCodes.ConstraintName: _constraintName = PGUtil.ReadString(stream); ; break; default: // Unknown error field; consume and discard. PGUtil.ReadString(stream); ; break; } } } break; } }
/*/// <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, settings); } catch (NpgsqlException ne) { if (_stream != null) { try { _stream.Dispose(); } catch { } } 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, this.settings); } // Change the state of connection to open and ready. _connection_state = ConnectionState.Open; CurrentState = NpgsqlReadyState.Instance; // After attachment, the stream will close the connector (this) when the stream gets disposed. _baseStream.AttachConnector(this); // 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())); } } ProcessServerVersion(); StringBuilder sbInitQueries = new StringBuilder(); if (BackendProtocolVersion == ProtocolVersion.Version2) { sbInitQueries.Append("set DATESTYLE TO ISO;"); // 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)) ) { sbInitQueries.Append("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(); } // This is using string concatenation because set search_path doesn't allow type casting. ::text sbInitQueries.Append("SET SEARCH_PATH=") .Append(settings.SearchPath) .Append(";"); } 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(); } sbInitQueries.Append("SET APPLICATION_NAME='") .Append(settings.ApplicationName) .Append("';"); } /* * 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. */ if (SupportsSslRenegotiationLimit) { sbInitQueries.Append("SET ssl_renegotiation_limit=0;"); } /* * Set precision digits to maximum value possible. For postgresql before 9 it was 2, after that, it is 3. * Check bug report #1010992 for more information. */ if (SupportsExtraFloatDigits3) { sbInitQueries.Append("SET extra_float_digits=3;"); } else if (SupportsExtraFloatDigits) { sbInitQueries.Append("SET extra_float_digits=2;"); } /* * Set lc_monetary format to 'C' in 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. */ sbInitQueries.Append("SET lc_monetary='C';"); } else { // Some connection parameters for protocol 3 had been sent in the startup packet. // The rest will be setted here. if (SupportsExtraFloatDigits3) { sbInitQueries.Append("SET extra_float_digits=3;"); } if (SupportsSslRenegotiationLimit) { sbInitQueries.Append("SET ssl_renegotiation_limit=0;"); } } initQueries = sbInitQueries.ToString(); NpgsqlCommand initCommand = new NpgsqlCommand(initQueries, this); initCommand.ExecuteBlind(); // 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. NativeToBackendTypeConverterOptions.OidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone(); // 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; }
/// <summary> /// The function will modify private member only, not base[key]. /// </summary> /// <param name="keyword"></param> /// <param name="value"></param> private void SetValue(Keywords keyword, object value) { string key_name = GetKeyName(keyword); try { switch (keyword) { case Keywords.Host: this._host = Convert.ToString(value); break; case Keywords.Port: this._port = Convert.ToInt32(value); break; case Keywords.Protocol: this._protocol = ToProtocolVersion(value); break; case Keywords.Database: this._database = Convert.ToString(value); break; case Keywords.UserName: this._username = Convert.ToString(value); break; case Keywords.Password: this._password = Convert.ToString(value); break; case Keywords.SSL: this._ssl = ToBoolean(value); break; case Keywords.SslMode: this._sslmode = ToSslMode(value); break; #pragma warning disable 618 case Keywords.Encoding: break; #pragma warning restore 618 case Keywords.Timeout: this._timeout = ToInt32(value, 0, TIMEOUT_LIMIT, key_name); break; case Keywords.SearchPath: this._searchpath = Convert.ToString(value); break; case Keywords.Pooling: this._pooling = ToBoolean(value); break; case Keywords.ConnectionLifeTime: this._connection_life_time = Convert.ToInt32(value); break; case Keywords.MinPoolSize: this._min_pool_size = (MaxPoolSize > 0) ? ToInt32(value, 0, MaxPoolSize, key_name) : Convert.ToInt32(value); break; case Keywords.MaxPoolSize: this._max_pool_size = ToInt32(value, 0, POOL_SIZE_LIMIT, key_name); break; case Keywords.SyncNotification: this._sync_notification = ToBoolean(value); break; case Keywords.CommandTimeout: this._command_timeout = Convert.ToInt32(value); break; case Keywords.Enlist: this._enlist = ToBoolean(value); break; case Keywords.PreloadReader: this._preloadReader = ToBoolean(value); break; case Keywords.UseExtendedTypes: this._useExtendedTypes = ToBoolean(value); break; case Keywords.IntegratedSecurity: this._integrated_security = ToIntegratedSecurity(value); break; } } catch (InvalidCastException exception) { string exception_template = string.Empty; switch (keyword) { case Keywords.Port: case Keywords.Timeout: case Keywords.ConnectionLifeTime: case Keywords.MinPoolSize: case Keywords.MaxPoolSize: case Keywords.CommandTimeout: exception_template = resman.GetString("Exception_InvalidIntegerKeyVal"); break; case Keywords.SSL: case Keywords.Pooling: case Keywords.SyncNotification: exception_template = resman.GetString("Exception_InvalidBooleanKeyVal"); break; case Keywords.Protocol: exception_template = resman.GetString("Exception_InvalidProtocolVersionKeyVal"); break; } if (!string.IsNullOrEmpty(exception_template)) { throw new ArgumentException(string.Format(exception_template, key_name), key_name, exception); } throw; } }
/*/// <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; }
public NpgsqlRow(NpgsqlRowDescription rowDesc, ProtocolVersion protocolVersion) { data = new ArrayList(); row_desc = rowDesc; protocol_version = protocolVersion; }
/// <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() { ProtocolVersion PV; // If Connection.ConnectionString specifies a protocol version, we will // not try to fall back to version 2 on failure. if (ConnectionString.Contains(ConnectionStringKeys.Protocol)) { PV = ConnectionString.ToProtocolVersion(ConnectionStringKeys.Protocol); } else { PV = ProtocolVersion.Unknown; } _backendProtocolVersion = (PV == ProtocolVersion.Unknown) ? ProtocolVersion.Version3 : PV; // Reset state to initialize new connector in pool. Encoding = Encoding.Default; CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this); // Establish protocol communication and handle authentication... CurrentState.Startup(this); // Check for protocol not supported. If we have been told what protocol to use, // we will not try this step. if (_mediator.Errors.Count > 0 && PV == ProtocolVersion.Unknown) { // If we attempted protocol version 3, it may be possible to drop back to version 2. if (BackendProtocolVersion == ProtocolVersion.Version3) { NpgsqlError Error0 = (NpgsqlError)_mediator.Errors[0]; // If NpgsqlError.ReadFromStream_Ver_3() 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) { // 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); } } } // Check for errors and do the Right Thing. // FIXME - CheckErrors needs to be moved to Connector CheckErrors(); _backend_keydata = _mediator.BackendKeyData; // Change the state of connection to open and ready. _connection_state = ConnectionState.Open; CurrentState = NpgsqlReadyState.Instance; String ServerVersionString = String.Empty; // First try to determine backend server version using the newest method. if (((NpgsqlParameterStatus)_mediator.Parameters["__npgsql_server_version"]) != null) { ServerVersionString = ((NpgsqlParameterStatus)_mediator.Parameters["__npgsql_server_version"]).ParameterValue; } // Fall back to the old way, SELECT VERSION(). // This should not happen for protocol version 3+. if (ServerVersionString.Length == 0) { NpgsqlCommand command = new NpgsqlCommand("select version();set DATESTYLE TO ISO;", this); ServerVersionString = PGUtil.ExtractServerVersion((String)command.ExecuteScalar()); } // Cook version string so we can use it for enabling/disabling things based on // backend version. ServerVersion = PGUtil.ParseServerVersion(ServerVersionString); // Adjust client encoding. //NpgsqlCommand commandEncoding1 = new NpgsqlCommand("show client_encoding", _connector); //String clientEncoding1 = (String)commandEncoding1.ExecuteScalar(); if (ConnectionString.ToString(ConnectionStringKeys.Encoding, ConnectionStringDefaults.Encoding).ToUpper() == "UNICODE") { Encoding = Encoding.UTF8; NpgsqlCommand commandEncoding = new NpgsqlCommand("SET CLIENT_ENCODING TO UNICODE", this); commandEncoding.ExecuteNonQuery(); } // 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; }