Beispiel #1
0
        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;
            }
        }
Beispiel #2
0
 internal NpgsqlError(ProtocolVersion protocolVersion, String errorMessage)
 {
     protocol_version = protocolVersion;
     _message         = errorMessage;
 }
Beispiel #3
0
 public NpgsqlQuery(NpgsqlCommand command, ProtocolVersion protocolVersion)
 {
     _command         = command;
     _protocolVersion = protocolVersion;
 }
Beispiel #4
0
        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;
            }
        }
Beispiel #5
0
        /*/// <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;
 }
Beispiel #9
0
        /// <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;
        }