示例#1
0
        void ProcessRawQuery()
        {
            _queries.Clear();
            switch (CommandType)
            {
            case CommandType.Text:
                SqlQueryParser.ParseRawQuery(CommandText, _connection == null || _connection.UseConformantStrings, _parameters, _queries);
                if (_queries.Count > 1 && _parameters.Any(p => p.IsOutputDirection))
                {
                    throw new NotSupportedException("Commands with multiple queries cannot have out parameters");
                }
                break;

            case CommandType.TableDirect:
                _queries.Add(new NpgsqlStatement("SELECT * FROM " + CommandText, new List <NpgsqlParameter>()));
                break;

            case CommandType.StoredProcedure:
                var numInput = _parameters.Count(p => p.IsInputDirection);
                var sb       = new StringBuilder();
                sb.Append("SELECT * FROM ");
                sb.Append(CommandText);
                sb.Append('(');
                for (var i = 1; i <= numInput; i++)
                {
                    sb.Append('$');
                    sb.Append(i);
                    if (i < numInput)
                    {
                        sb.Append(',');
                    }
                }
                sb.Append(')');
                _queries.Add(new NpgsqlStatement(sb.ToString(), _parameters.Where(p => p.IsInputDirection).ToList()));
                break;

            default:
                throw PGUtil.ThrowIfReached();
            }
        }
示例#2
0
        /// <summary>
        /// Creates a prepared version of the command on a PostgreSQL server.
        /// </summary>
        public override void Prepare()
        {
            Prechecks();
            if (Parameters.Any(p => !p.IsTypeExplicitlySet))
            {
                throw new InvalidOperationException("NpgsqlCommand.Prepare method requires all parameters to have an explicitly set type.");
            }

            _connector = Connection.Connector;
            Log.Debug("Prepare command", _connector.Id);

            using (_connector.StartUserAction())
            {
                DeallocatePrepared();
                ProcessRawQuery();

                for (var i = 0; i < _queries.Count; i++)
                {
                    var             query = _queries[i];
                    ParseMessage    parseMessage;
                    DescribeMessage describeMessage;
                    if (i == 0)
                    {
                        parseMessage    = _connector.ParseMessage;
                        describeMessage = _connector.DescribeMessage;
                    }
                    else
                    {
                        parseMessage    = new ParseMessage();
                        describeMessage = new DescribeMessage();
                    }

                    query.PreparedStatementName = _connector.NextPreparedStatementName();
                    _connector.AddMessage(parseMessage.Populate(query, _connector.TypeHandlerRegistry));
                    _connector.AddMessage(describeMessage.Populate(StatementOrPortal.Statement,
                                                                   query.PreparedStatementName));
                }

                _connector.AddMessage(SyncMessage.Instance);
                _connector.SendAllMessages();

                _queryIndex = 0;

                while (true)
                {
                    var msg = _connector.ReadSingleMessage();
                    switch (msg.Code)
                    {
                    case BackendMessageCode.CompletedResponse: // prepended messages, e.g. begin transaction
                    case BackendMessageCode.ParseComplete:
                    case BackendMessageCode.ParameterDescription:
                        continue;

                    case BackendMessageCode.RowDescription:
                        var description = (RowDescriptionMessage)msg;
                        FixupRowDescription(description, _queryIndex == 0);
                        _queries[_queryIndex++].Description = description;
                        continue;

                    case BackendMessageCode.NoData:
                        _queries[_queryIndex++].Description = null;
                        continue;

                    case BackendMessageCode.ReadyForQuery:
                        Contract.Assume(_queryIndex == _queries.Count);
                        IsPrepared = true;
                        return;

                    default:
                        throw _connector.UnexpectedMessageReceived(msg.Code);
                    }
                }
            }
        }