ExecuteBlind() 개인적인 정적인 메소드

private static ExecuteBlind ( NpgsqlConnector connector, NpgsqlQuery query, int timeout ) : void
connector NpgsqlConnector
query NpgsqlQuery
timeout int
리턴 void
예제 #1
0
        /// <summary>
        /// This method is responsible to release all portals used by this Connector.
        /// </summary>
        internal void ReleasePlansPortals()
        {
            Int32 i = 0;

            if (_planIndex > 0)
            {
                for (i = 1; i <= _planIndex; i++)
                {
                    try
                    {
                        //Query(new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i), this));
                        using (NpgsqlCommand cmd = new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i.ToString()), this))
                        {
                            cmd.ExecuteBlind();
                        }
                    }

                    // Ignore any error which may occur when releasing portals as this portal name may not be valid anymore. i.e.: the portal name was used on a prepared query which had errors.
                    catch (Exception) {}
                }
            }

            _portalIndex = 0;
            _planIndex   = 0;
        }
예제 #2
0
        internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);

            _conn = conn;
            _isolation = isolation;

            StringBuilder commandText = new StringBuilder("BEGIN; SET TRANSACTION ISOLATION LEVEL ");

            if ((isolation == IsolationLevel.RepeatableRead) ||
                (isolation == IsolationLevel.Serializable) ||
                (isolation == IsolationLevel.Snapshot))
            {
                commandText.Append("SERIALIZABLE");
            }
            else
            {
                // Set isolation level default to read committed.
                _isolation = IsolationLevel.ReadCommitted;
                commandText.Append("READ COMMITTED");
            }

            commandText.Append(";");

            NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector);
            command.ExecuteBlind();
            _conn.Connector.Transaction = this;
        }
예제 #3
0
        internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);

            _conn      = conn;
            _isolation = isolation;

            if (isolation == IsolationLevel.RepeatableRead)
            {
                NpgsqlCommand.ExecuteBlind(conn.Connector, NpgsqlQuery.BeginTransRepeatableRead);
            }
            else if ((isolation == IsolationLevel.Serializable) ||
                     (isolation == IsolationLevel.Snapshot))
            {
                NpgsqlCommand.ExecuteBlind(conn.Connector, NpgsqlQuery.BeginTransSerializable);
            }
            else
            {
                // Set isolation level default to read committed.
                _isolation = IsolationLevel.ReadCommitted;
                NpgsqlCommand.ExecuteBlind(conn.Connector, NpgsqlQuery.BeginTransReadCommitted);
            }

            _conn.Connector.Transaction = this;
        }
예제 #4
0
        internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME);

            _conn      = conn;
            _isolation = isolation;

            StringBuilder commandText = new StringBuilder("BEGIN; SET TRANSACTION ISOLATION LEVEL ");

            if ((isolation == IsolationLevel.RepeatableRead) ||
                (isolation == IsolationLevel.Serializable) ||
                (isolation == IsolationLevel.Snapshot))
            {
                commandText.Append("SERIALIZABLE");
            }
            else
            {
                // Set isolation level default to read committed.
                _isolation = IsolationLevel.ReadCommitted;
                commandText.Append("READ COMMITTED");
            }

            commandText.Append(";");

            NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector);

            command.ExecuteBlind();
            _conn.Connector.Transaction = this;
        }
예제 #5
0
        /// <summary>
        /// Creates a transaction save point.
        /// </summary>

        public void Save(String savePointName)
        {
            CheckDisposed();

            if (_conn == null)
            {
                throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
            }

            if (!_conn.Connector.SupportsSavepoint)
            {
                throw new InvalidOperationException(resman.GetString("Exception_SavePointNotSupported"));
            }


            if (savePointName.Contains(";"))
            {
                throw new InvalidOperationException(resman.GetString("Exception_SavePointWithSemicolon"));
            }


            NpgsqlCommand command = new NpgsqlCommand("SAVEPOINT " + savePointName, _conn.Connector);

            command.ExecuteBlind();
        }
예제 #6
0
 internal void ReleaseRegisteredListen()
 {
     //Query(new NpgsqlCommand("unlisten *", this));
     using (NpgsqlCommand cmd = new NpgsqlCommand("unlisten *", this))
     {
         cmd.ExecuteBlind();
     }
 }
예제 #7
0
        internal void ReleaseWithDiscard()
        {
            using (NpgsqlCommand cmd = new NpgsqlCommand("DISCARD ALL", this, 60))
            {
                cmd.ExecuteBlind();
            }

            // The initial connection parameters will be restored via IsValid() when get connector from pool later
        }
예제 #8
0
 public void PrepareTransaction()
 {
     if (!_prepared)
     {
         NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "PrepareTransaction");
         NpgsqlConnection connection = GetConnection();
         NpgsqlCommand.ExecuteBlind(connection.Connector, string.Format("PREPARE TRANSACTION '{0}'", _txName));
         _prepared = true;
     }
 }
예제 #9
0
        public void TestNotify(NpgsqlConnector context)
        {
            //ZA  Hnotifytest CNOTIFY Z
            //Qlisten notifytest;notify notifytest;
            Stream stm = context.Stream;
//            string uuidString = "uuid" + Guid.NewGuid().ToString("N");
            string       uuidString = string.Format("uuid{0:N}", Guid.NewGuid());
            Queue <byte> buffer     = new Queue <byte>();

            byte[] convertBuffer = new byte[36];

            PGUtil.WriteStringNullTerminated(stm, "Qlisten {0};notify {0};", uuidString);

            for (;;)
            {
                int newByte = stm.ReadByte();
                if (newByte == -1)
                {
                    throw new EndOfStreamException();
                }
                buffer.Enqueue((byte)newByte);
                if (buffer.Count > 35)
                {
                    buffer.CopyTo(convertBuffer, 0);
                    if (BackendEncoding.UTF8Encoding.GetString(convertBuffer) == uuidString)
                    {
                        for (;;)
                        {
                            switch (stm.ReadByte())
                            {
                            case -1:
                                throw new EndOfStreamException();

                            case 'Z':
                                //context.Query(new NpgsqlCommand("UNLISTEN *", context));
                                using (NpgsqlCommand cmd = new NpgsqlCommand("UNLISTEN *", context))
                                {
                                    cmd.ExecuteBlind();
                                }
                                return;
                            }
                        }
                    }
                    else
                    {
                        buffer.Dequeue();
                    }
                }
            }
        }
예제 #10
0
        public void CommitTransaction()
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "CommitTransaction");
            NpgsqlConnection connection = GetConnection();

            if (_prepared)
            {
                NpgsqlCommand.ExecuteBlind(connection.Connector, string.Format("COMMIT PREPARED '{0}'", _txName));
            }
            else
            {
                NpgsqlCommand.ExecuteBlind(connection.Connector, NpgsqlQuery.CommitTransaction);
            }
        }
예제 #11
0
        public void RollbackTransaction()
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "RollbackTransaction");
            NpgsqlConnection connection = GetConnection();

            if (_prepared)
            {
                NpgsqlCommand.ExecuteBlind(connection.Connector, string.Format("ROLLBACK PREPARED '{0}'", _txName));
            }
            else
            {
                NpgsqlCommand.ExecuteBlind(connection.Connector, "ROLLBACK");
            }
        }
예제 #12
0
        /// <summary>
        /// Rolls back a transaction from a pending state.
        /// </summary>
        public override void Rollback()
        {
            CheckDisposed();

            if (_conn == null)
            {
                throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
            }

            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Rollback");

            NpgsqlCommand.ExecuteBlind(_conn.Connector, NpgsqlQuery.RollbackTransaction);
            _conn.Connector.Transaction = null;
            _conn = null;
        }
예제 #13
0
        /// <summary>
        /// Commits the database transaction.
        /// </summary>
        public override void Commit()
        {
            CheckDisposed();

            if (_conn == null)
            {
                throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
            }

            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Commit");

            NpgsqlCommand command = new NpgsqlCommand("COMMIT", _conn.Connector);

            command.ExecuteBlind();
            _conn.Connector.Transaction = null;
            _conn = null;
        }
예제 #14
0
 /// <summary>
 /// Command specified upon creation is executed as a non-query.
 /// If CopyStream is set upon creation, it will be flushed to server as copy data, and operation will be finished immediately.
 /// Otherwise the CopyStream member can be used for writing copy data to server and operation finished with a call to End() or Cancel().
 /// </summary>
 public void Start()
 {
     if (_context.CurrentState is NpgsqlReadyState)
     {
         _context.Mediator.CopyStream = _copyStream;
         _cmd.ExecuteBlind();
         _disposeCopyStream = _copyStream == null;
         _copyStream        = _context.Mediator.CopyStream;
         if (_copyStream == null && !(_context.CurrentState is NpgsqlReadyState))
         {
             throw new NpgsqlException("Not a COPY IN query: " + _cmd.CommandText);
         }
     }
     else
     {
         throw new NpgsqlException("Copy can only start in Ready state, not in " + _context.CurrentState);
     }
 }
예제 #15
0
        /// <summary>
        /// This method is responsible to release all portals used by this Connector.
        /// </summary>
        internal void ReleasePlansPortals()
        {
            Int32 i = 0;

            if (_planIndex > 0)
            {
                for (i = 1; i <= _planIndex; i++)
                {
                    try
                    {
                        NpgsqlCommand.ExecuteBlind(this, String.Format("DEALLOCATE \"{0}{1}\";", _planNamePrefix, i), -1);
                    }
                    // Ignore any error which may occur when releasing portals as this portal name may not be valid anymore. i.e.: the portal name was used on a prepared query which had errors.
                    catch {}
                }
            }

            _portalIndex = 0;
            _planIndex   = 0;
        }
예제 #16
0
        /// <summary>
        /// Rolls back a transaction from a pending savepoint state.
        /// </summary>
        public void Rollback(String savePointName)
        {
            CheckDisposed();

            if (_conn == null)
            {
                throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
            }

            if (!_conn.Connector.SupportsSavepoint)
            {
                throw new InvalidOperationException(resman.GetString("Exception_SavePointNotSupported"));
            }

            if (savePointName.Contains(";"))
            {
                throw new InvalidOperationException(resman.GetString("Exception_SavePointWithSemicolon"));
            }

            NpgsqlCommand.ExecuteBlind(_conn.Connector, string.Format("ROLLBACK TO SAVEPOINT {0}", savePointName));
        }
예제 #17
0
 public void PrepareTransaction()
 {
     if (!_prepared)
     {
         NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "PrepareTransaction");
         NpgsqlConnection connection = GetConnection();
         NpgsqlCommand command = new NpgsqlCommand(string.Format("PREPARE TRANSACTION '{0}'", _txName), connection);
         command.ExecuteBlind();
         _prepared = true;
     }
 }
예제 #18
0
        /// <summary>
        /// Creates a prepared version of the command on a PostgreSQL server.
        /// </summary>
        public override void Prepare()
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Prepare");

            // Check the connection state.
            CheckConnectionState();

            // reset any responses just before getting new ones
            Connector.Mediator.ResetResponses();

            // Set command timeout.
            m_Connector.Mediator.CommandTimeout = CommandTimeout;

            if (!m_Connector.SupportsPrepare)
            {
                return; // Do nothing.
            }

            if (m_Connector.BackendProtocolVersion == ProtocolVersion.Version2)
            {
                using (NpgsqlCommand command = new NpgsqlCommand(GetPrepareCommandText(), m_Connector))
                {
                    command.ExecuteBlind();
                }
            }
            else
            {
                using (m_Connector.BlockNotificationThread())
                {
                    try
                    {
                        // Use the extended query parsing...
                        planName = m_Connector.NextPlanName();
                        String portalName = m_Connector.NextPortalName();

                        parse = new NpgsqlParse(planName, GetParseCommandText(), new Int32[] { });

                        m_Connector.Parse(parse);

                        // We need that because Flush() doesn't cause backend to send
                        // ReadyForQuery on error. Without ReadyForQuery, we don't return 
                        // from query extended processing.

                        // We could have used Connector.Flush() which sends us back a
                        // ReadyForQuery, but on postgresql server below 8.1 there is an error
                        // with extended query processing which hinders us from using it.
                        m_Connector.RequireReadyForQuery = false;
                        m_Connector.Flush();


                        // Description...
                        NpgsqlDescribe describe = new NpgsqlDescribe('S', planName);


                        m_Connector.Describe(describe);

                        NpgsqlRowDescription returnRowDesc = m_Connector.Sync();

                        Int16[] resultFormatCodes;


                        if (returnRowDesc != null)
                        {
                            resultFormatCodes = new Int16[returnRowDesc.NumFields];

                            for (int i = 0; i < returnRowDesc.NumFields; i++)
                            {
                                NpgsqlRowDescription.FieldData returnRowDescData = returnRowDesc[i];


                                if (returnRowDescData.TypeInfo != null && returnRowDescData.TypeInfo.NpgsqlDbType == NpgsqlDbType.Bytea)
                                {
                                    // Binary format
                                    resultFormatCodes[i] = (Int16)FormatCode.Binary;
                                }
                                else
                                {
                                    // Text Format
                                    resultFormatCodes[i] = (Int16)FormatCode.Text;
                                }
                            }
                        }
                        else
                        {
                            resultFormatCodes = new Int16[] { 0 };
                        }

                        bind = new NpgsqlBind("", planName, new Int16[Parameters.Count], null, resultFormatCodes);
                    }
                    catch (IOException e)
                    {
                        throw ClearPoolAndCreateException(e);
                    }
                    catch
                    {

                        // As per documentation:

                        // "[...] When an error is detected while processing any extended-query message,

                        // the backend issues ErrorResponse, then reads and discards messages until a

                        // Sync is reached, then issues ReadyForQuery and returns to normal message processing.[...]"

                        // So, send a sync command if we get any problems.



                        m_Connector.Sync();

                        throw;
                    }
                }
            }
        }
예제 #19
0
 internal void ReleaseRegisteredListen()
 {
     NpgsqlCommand.ExecuteBlind(this, "UNLISTEN *");
 }
예제 #20
0
        /// <summary>
        /// This method is responsible to release all portals used by this Connector.
        /// </summary>
        internal void ReleasePlansPortals()
        {
            Int32 i = 0;

            if (_planIndex > 0)
            {
                for (i = 1; i <= _planIndex; i++)
                {
                    try
                    {
                        //Query(new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i), this));
                        using(NpgsqlCommand cmd = new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i.ToString()), this))
                        {
                            cmd.ExecuteBlind();
                        }
                    }

                    // Ignore any error which may occur when releasing portals as this portal name may not be valid anymore. i.e.: the portal name was used on a prepared query which had errors.
                    catch(Exception) {}
                }
            }

            _portalIndex = 0;
            _planIndex = 0;
        }
예제 #21
0
        internal void ReleaseWithDiscard()
        {
            NpgsqlCommand.ExecuteBlind(this, NpgsqlQuery.DiscardAll, 60);

            // The initial connection parameters will be restored via IsValid() when get connector from pool later
        }
예제 #22
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;

            // 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();
            }

            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 {}

            // 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;
        }
        private void PrepareInternal()
        {
            if (m_Connector.BackendProtocolVersion == ProtocolVersion.Version2)
            {
                planName = Connector.NextPlanName();

                // BackendEncoding.UTF8Encoding.GetString() is temporary.  A new optimization for
                // ExecuteBlind() will negate the need.
                using (NpgsqlCommand command = new NpgsqlCommand(BackendEncoding.UTF8Encoding.GetString(GetCommandText(true, false)), m_Connector))
                {
                    command.ExecuteBlind();
                    prepared = PrepareStatus.V2Prepared;
                }
            }
            else
            {
                // Use the extended query parsing...
                planName = m_Connector.NextPlanName();
                String portalName = "";
                NpgsqlParse parse = new NpgsqlParse(planName,  GetCommandText(true, true), new Int32[] { });
                NpgsqlDescribe statementDescribe = new NpgsqlDescribeStatement(planName);
                IEnumerable<IServerResponseObject> responseEnum;
                NpgsqlRowDescription returnRowDesc = null;

                // Write Parse, Describe, and Sync messages to the wire.
                m_Connector.Parse(parse);
                m_Connector.Describe(statementDescribe);
                m_Connector.Sync();

                // Flush and wait for response.
                responseEnum = m_Connector.ProcessBackendResponsesEnum();

                // Look for a NpgsqlRowDescription in the responses, discarding everything else.
                foreach (IServerResponseObject response in responseEnum)
                {
                    if (response is NpgsqlRowDescription)
                    {
                        returnRowDesc = (NpgsqlRowDescription)response;
                    }
                    else if (response is IDisposable)
                    {
                        (response as IDisposable).Dispose();
                    }
                }

                Int16[] resultFormatCodes;

                if (returnRowDesc != null)
                {
                    resultFormatCodes = new Int16[returnRowDesc.NumFields];

                    for (int i = 0; i < returnRowDesc.NumFields; i++)
                    {
                        NpgsqlRowDescription.FieldData returnRowDescData = returnRowDesc[i];

                        if (returnRowDescData.TypeInfo != null)
                        {
                            // Binary format?
                            // PG always defaults to text encoding.  We can fix up the row description
                            // here based on support for binary encoding.  Once this is done,
                            // there is no need to request another row description after Bind.
                            returnRowDescData.FormatCode = returnRowDescData.TypeInfo.SupportsBinaryBackendData ? FormatCode.Binary : FormatCode.Text;
                            resultFormatCodes[i] = (Int16)returnRowDescData.FormatCode;
                        }
                        else
                        {
                            // Text format (default).
                            resultFormatCodes[i] = (Int16)FormatCode.Text;
                        }
                    }
                }
                else
                {
                    resultFormatCodes = new Int16[] { 0 };
                }

                // Save the row description for use with all future Executes.
                currentRowDescription = returnRowDesc;

                // The Bind and Execute message objects live through multiple Executes.
                // Only Bind changes at all between Executes, which is done in BindParameters().
                bind = new NpgsqlBind(portalName, planName, new Int16[Parameters.Count], null, resultFormatCodes);
                execute = new NpgsqlExecute(portalName, 0);

                prepared = PrepareStatus.V3Prepared;
            }
        }
예제 #24
0
 internal void ReleaseRegisteredListen()
 {
     //Query(new NpgsqlCommand("unlisten *", this));
     using(NpgsqlCommand cmd = new NpgsqlCommand("unlisten *", this))
     {
         cmd.ExecuteBlind();
     }
 }
예제 #25
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);
            }
            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;
        }
        internal ForwardsOnlyDataReader GetReader(CommandBehavior cb)
        {
            CheckConnectionState();

            // reset any responses just before getting new ones
            Connector.Mediator.ResetResponses();

            // Set command timeout.
            m_Connector.Mediator.CommandTimeout = CommandTimeout;

            // Block the notification thread before writing anything to the wire.
            using (m_Connector.BlockNotificationThread())
            {
                IEnumerable <IServerResponseObject> responseEnum;
                ForwardsOnlyDataReader reader;

                if (m_Connector.CommandTimeoutSent == -1 || m_Connector.CommandTimeoutSent != this.CommandTimeout)
                {
                    NpgsqlCommand toq = new NpgsqlCommand(string.Format("SET statement_timeout = {0}", this.CommandTimeout * 1000), m_Connector);

                    toq.ExecuteBlind();

                    m_Connector.CommandTimeoutSent = this.CommandTimeout;
                }

                if (prepared == PrepareStatus.NeedsPrepare)
                {
                    PrepareInternal();
                }

                if (prepared == PrepareStatus.NotPrepared || prepared == PrepareStatus.V2Prepared)
                {
                    NpgsqlQuery query;

                    query = new NpgsqlQuery(m_Connector, GetCommandText());

                    // Write the Query message to the wire.
                    m_Connector.Query(query);

                    // Flush and wait for responses.
                    responseEnum = m_Connector.ProcessBackendResponsesEnum();

                    // Construct the return reader.
                    reader = new ForwardsOnlyDataReader(
                        responseEnum,
                        cb,
                        this,
                        m_Connector.BlockNotificationThread()
                        );

                    if (
                        commandType == CommandType.StoredProcedure &&
                        reader.FieldCount == 1 &&
                        reader.GetDataTypeName(0) == "refcursor"
                        )
                    {
                        // When a function returns a sole column of refcursor, transparently
                        // FETCH ALL from every such cursor and return those results.
                        StringWriter sw = new StringWriter();
                        string       queryText;

                        while (reader.Read())
                        {
                            sw.WriteLine("FETCH ALL FROM \"{0}\";", reader.GetString(0));
                        }

                        reader.Dispose();

                        queryText = sw.ToString();

                        if (queryText == "")
                        {
                            queryText = ";";
                        }

                        // Passthrough the commandtimeout to the inner command, so user can also control its timeout.
                        // TODO: Check if there is a better way to handle that.

                        query = new NpgsqlQuery(m_Connector, queryText);

                        // Write the Query message to the wire.
                        m_Connector.Query(query);

                        // Flush and wait for responses.
                        responseEnum = m_Connector.ProcessBackendResponsesEnum();

                        // Construct the return reader.
                        reader = new ForwardsOnlyDataReader(
                            responseEnum,
                            cb,
                            this,
                            m_Connector.BlockNotificationThread()
                            );
                    }
                }
                else
                {
                    // Update the Bind object with current parameter data as needed.
                    BindParameters();

                    // Write the Bind, Execute, and Sync message to the wire.
                    m_Connector.Bind(bind);
                    m_Connector.Execute(execute);
                    m_Connector.Sync();

                    // Flush and wait for responses.
                    responseEnum = m_Connector.ProcessBackendResponsesEnum();

                    // Construct the return reader, possibly with a saved row description from Prepare().
                    reader = new ForwardsOnlyDataReader(
                        responseEnum,
                        cb,
                        this,
                        m_Connector.BlockNotificationThread(),
                        true,
                        currentRowDescription
                        );
                }

                return(reader);
            }
        }
        private void PrepareInternal()
        {
            if (m_Connector.BackendProtocolVersion == ProtocolVersion.Version2)
            {
                planName = Connector.NextPlanName();

                // BackendEncoding.UTF8Encoding.GetString() is temporary.  A new optimization for
                // ExecuteBlind() will negate the need.
                using (NpgsqlCommand command = new NpgsqlCommand(BackendEncoding.UTF8Encoding.GetString(GetCommandText(true, false)), m_Connector))
                {
                    command.ExecuteBlind();
                    prepared = PrepareStatus.V2Prepared;
                }
            }
            else
            {
                // Use the extended query parsing...
                planName = m_Connector.NextPlanName();
                String         portalName        = "";
                NpgsqlParse    parse             = new NpgsqlParse(planName, GetCommandText(true, true), new Int32[] { });
                NpgsqlDescribe statementDescribe = new NpgsqlDescribeStatement(planName);
                IEnumerable <IServerResponseObject> responseEnum;
                NpgsqlRowDescription returnRowDesc = null;

                // Write Parse, Describe, and Sync messages to the wire.
                m_Connector.Parse(parse);
                m_Connector.Describe(statementDescribe);
                m_Connector.Sync();

                // Flush and wait for response.
                responseEnum = m_Connector.ProcessBackendResponsesEnum();

                // Look for a NpgsqlRowDescription in the responses, discarding everything else.
                foreach (IServerResponseObject response in responseEnum)
                {
                    if (response is NpgsqlRowDescription)
                    {
                        returnRowDesc = (NpgsqlRowDescription)response;
                    }
                    else if (response is IDisposable)
                    {
                        (response as IDisposable).Dispose();
                    }
                }

                Int16[] resultFormatCodes;

                if (returnRowDesc != null)
                {
                    resultFormatCodes = new Int16[returnRowDesc.NumFields];

                    for (int i = 0; i < returnRowDesc.NumFields; i++)
                    {
                        NpgsqlRowDescription.FieldData returnRowDescData = returnRowDesc[i];

                        if (returnRowDescData.TypeInfo != null)
                        {
                            // Binary format?
                            // PG always defaults to text encoding.  We can fix up the row description
                            // here based on support for binary encoding.  Once this is done,
                            // there is no need to request another row description after Bind.
                            returnRowDescData.FormatCode = returnRowDescData.TypeInfo.SupportsBinaryBackendData ? FormatCode.Binary : FormatCode.Text;
                            resultFormatCodes[i]         = (Int16)returnRowDescData.FormatCode;
                        }
                        else
                        {
                            // Text format (default).
                            resultFormatCodes[i] = (Int16)FormatCode.Text;
                        }
                    }
                }
                else
                {
                    resultFormatCodes = new Int16[] { 0 };
                }

                // Save the row description for use with all future Executes.
                currentRowDescription = returnRowDesc;

                // The Bind and Execute message objects live through multiple Executes.
                // Only Bind changes at all between Executes, which is done in BindParameters().
                bind    = new NpgsqlBind(portalName, planName, new Int16[Parameters.Count], null, resultFormatCodes);
                execute = new NpgsqlExecute(portalName, 0);

                prepared = PrepareStatus.V3Prepared;
            }
        }
예제 #28
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.

            // 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)
            {
                if (_stream != null)
                {
                    try
                    {
                        _stream.Dispose();
                    }
                    catch
                    {
                    }
                }

                throw;
            }

            // 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();

            StringWriter sbInitQueries = new StringWriter();

            // Some connection parameters for protocol 3 had been sent in the startup packet.
            // The rest will be setted here.
            if (SupportsExtraFloatDigits3)
            {
                sbInitQueries.WriteLine("SET extra_float_digits=3;");
            }

            if (SupportsSslRenegotiationLimit)
            {
                sbInitQueries.WriteLine("SET ssl_renegotiation_limit=0;");
            }

            initQueries = sbInitQueries.ToString();

            NpgsqlCommand.ExecuteBlind(this, initQueries, 60);

            // 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;
        }
예제 #29
0
        public void TestNotify(NpgsqlConnector context)
        {
            //ZA  Hnotifytest CNOTIFY Z
            //Qlisten notifytest;notify notifytest;
            Stream stm = context.Stream;
            //            string uuidString = "uuid" + Guid.NewGuid().ToString("N");
            string uuidString = string.Format("uuid{0:N}", Guid.NewGuid());
            Queue<byte> buffer = new Queue<byte>();
            byte[] convertBuffer = new byte[36];

            PGUtil.WriteStringNullTerminated(stm, "Qlisten {0};notify {0};", uuidString);

            for (;;)
            {
                int newByte = stm.ReadByte();
                if (newByte == -1)
                {
                    throw new EndOfStreamException();
                }
                buffer.Enqueue((byte) newByte);
                if (buffer.Count > 35)
                {
                    buffer.CopyTo(convertBuffer, 0);
                    if (BackendEncoding.UTF8Encoding.GetString(convertBuffer) == uuidString)
                    {
                        for (;;)
                        {
                            switch (stm.ReadByte())
                            {
                                case -1:
                                    throw new EndOfStreamException();
                                case 'Z':
                                    //context.Query(new NpgsqlCommand("UNLISTEN *", context));
                                    using(NpgsqlCommand cmd = new NpgsqlCommand("UNLISTEN *", context))
                                    {
                                        cmd.ExecuteBlind();
                                    }
                                    return;
                            }
                        }
                    }
                    else
                    {
                        buffer.Dequeue();
                    }
                }
            }
        }
예제 #30
0
 internal void ReleaseRegisteredListen()
 {
     NpgsqlCommand.ExecuteBlind(this, NpgsqlQuery.UnlistenAll);
 }
예제 #31
0
        /// <summary>
        /// Rolls back a transaction from a pending state.
        /// </summary>
        public override void Rollback()
        {
            CheckDisposed();

            if (_conn == null)
            {
                throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
            }

            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Rollback");

            NpgsqlCommand command = new NpgsqlCommand("ROLLBACK", _conn.Connector);
            command.ExecuteBlind();
            _conn.Connector.Transaction = null;
            _conn = null;
        }
예제 #32
0
        /// <summary>
        /// Creates a transaction save point.
        /// </summary>

        public void Save(String savePointName)
        {
            
            CheckDisposed();

            if (_conn == null)
            {
                throw new InvalidOperationException(resman.GetString("Exception_NoTransaction"));
            }
            
            if (!_conn.Connector.SupportsSavepoint)
            {
                throw new InvalidOperationException(resman.GetString("Exception_SavePointNotSupported"));
            }
                
            
            if (savePointName.Contains(";"))
            {
                throw new InvalidOperationException(resman.GetString("Exception_SavePointWithSemicolon"));
                      
            }
            
            
            NpgsqlCommand command = new NpgsqlCommand("SAVEPOINT " + savePointName, _conn.Connector);
            command.ExecuteBlind();
            
        }
예제 #33
0
        internal void ReleaseWithDiscard()
        {
            using (NpgsqlCommand cmd = new NpgsqlCommand("DISCARD ALL", this, 60))
            {
                cmd.ExecuteBlind();
            }

            // The initial connection parameters will be restored via IsValid() when get connector from pool later
        }
예제 #34
0
        /// <summary>
        /// Modify the backend statement_timeout value if needed.
        /// </summary>
        /// <param name="timeout">New timeout</param>
        internal void SetBackendCommandTimeout(int timeout)
        {
            if (Mediator.BackendCommandTimeout == -1 || Mediator.BackendCommandTimeout != timeout)
            {
                NpgsqlCommand toq = new NpgsqlCommand(string.Format("SET statement_timeout = {0}", timeout * 1000), this);

                toq.ExecuteBlind();

                Mediator.BackendCommandTimeout = timeout;
            }
        }
예제 #35
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();

            StringWriter sbInitQueries = new StringWriter();

            if (BackendProtocolVersion == ProtocolVersion.Version2)
            {
                sbInitQueries.WriteLine("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.WriteLine("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.WriteLine("SET SEARCH_PATH = {0};", 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();
                    }

                    sbInitQueries.WriteLine("SET APPLICATION_NAME='{0}';", settings.ApplicationName);
                }

                /*
                 * 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.WriteLine("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.WriteLine("SET extra_float_digits=3;");
                }
                else if (SupportsExtraFloatDigits)
                {
                    sbInitQueries.WriteLine("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.WriteLine("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.WriteLine("SET extra_float_digits=3;");
                }

                if (SupportsSslRenegotiationLimit)
                {
                    sbInitQueries.WriteLine("SET ssl_renegotiation_limit=0;");
                }

            }

            initQueries = sbInitQueries.ToString();

            NpgsqlCommand initCommand = new NpgsqlCommand(initQueries, this, 60);
            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;
        }
예제 #36
0
        private void PrepareInternal()
        {
            if (m_Connector.BackendProtocolVersion == ProtocolVersion.Version2)
            {
                using (NpgsqlCommand command = new NpgsqlCommand(GetPrepareCommandText(), m_Connector))
                {
                    command.ExecuteBlind();
                    prepared = PrepareStatus.V2Prepared;
                }
            }
            else
            {
                // Use the extended query parsing...
                planName = m_Connector.NextPlanName();
                String portalName = "";
                NpgsqlParse parse = new NpgsqlParse(planName, GetParseCommandText(), new Int32[] { });
                NpgsqlDescribe statementDescribe = new NpgsqlDescribeStatement(planName);
                IEnumerable<IServerResponseObject> responseEnum;
                NpgsqlRowDescription returnRowDesc = null;

                // Write Parse, Describe, and Sync messages to the wire.
                m_Connector.Parse(parse);
                m_Connector.Describe(statementDescribe);
                m_Connector.Sync();

                // Flush and wait for response.
                responseEnum = m_Connector.ProcessBackendResponsesEnum();

                // Look for a NpgsqlRowDescription in the responses, discarding everything else.
                foreach (IServerResponseObject response in responseEnum)
                {
                    if (response is NpgsqlRowDescription)
                    {
                        returnRowDesc = (NpgsqlRowDescription)response;
                    }
                    else if (response is IDisposable)
                    {
                        (response as IDisposable).Dispose();
                    }
                }

                Int16[] resultFormatCodes;

                if (returnRowDesc != null)
                {
                    resultFormatCodes = new Int16[returnRowDesc.NumFields];

                    for (int i = 0; i < returnRowDesc.NumFields; i++)
                    {
                        NpgsqlRowDescription.FieldData returnRowDescData = returnRowDesc[i];

                        if (returnRowDescData.TypeInfo != null)
                        {
                            // Binary format?
                            resultFormatCodes[i] = returnRowDescData.TypeInfo.SupportsBinaryBackendData ? (Int16)FormatCode.Binary : (Int16)FormatCode.Text;
                        }
                        else
                        {
                            // Text Format
                            resultFormatCodes[i] = (Int16)FormatCode.Text;
                        }
                    }
                }
                else
                {
                    resultFormatCodes = new Int16[] { 0 };
                }

                // The Bind and Execute message objects live through multiple Executes.
                // Only Bind changes at all between Executes, which is done in BindParameters().
                bind = new NpgsqlBind(portalName, planName, new Int16[Parameters.Count], null, resultFormatCodes);
                execute = new NpgsqlExecute(portalName, 0);
                prepared = PrepareStatus.V3Prepared;
            }
        }
예제 #37
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;

            // 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;
        }