Ejemplo n.º 1
0
        internal override bool Write(WriteBuffer buf)
        {
            if (_charPos == -1)
            {
                // Start new query
                if (buf.WriteSpaceLeft < 1 + 4)
                    return false;
                _charPos = 0;
                var queryByteLen = PGUtil.UTF8Encoding.GetByteCount(_query);
                _queryChars = _query.ToCharArray();
                buf.WriteByte(Code);
                buf.WriteInt32(4 +            // Message length (including self excluding code)
                               queryByteLen + // Query byte length
                               1);            // Null terminator
            }

            if (_charPos < _queryChars.Length)
            {
                int charsUsed;
                bool completed;
                buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                       out charsUsed, out completed);
                _charPos += charsUsed;
                if (!completed)
                    return false;
            }

            if (buf.WriteSpaceLeft < 1)
                return false;
            buf.WriteByte(0);

            _charPos = -1;
            return true;
        }
Ejemplo n.º 2
0
        internal override void WriteFully(WriteBuffer buf)
        {
            Contract.Requires(Name != null && Name.All(c => c < 128));

            buf.WriteByte(Code);
            buf.WriteInt32(Length - 1);
            buf.WriteByte((byte)StatementOrPortal);
            buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Name));
        }
Ejemplo n.º 3
0
 internal override void WriteFully(WriteBuffer buf)
 {
     buf.WriteByte(Code);
     buf.WriteInt32(Length - 1);
     if (_errorMessageLen == 0)
     {
         buf.WriteByte(0);
     }
     else
     {
         buf.WriteBytesNullTerminated(PGUtil.UTF8Encoding.GetBytes(_errorMessage));
     }
 }
        internal Task WriteClose(StatementOrPortal type, string name, bool async, CancellationToken cancellationToken = default)
        {
            var len = sizeof(byte) +               // Message code
                      sizeof(int) +                // Length
                      sizeof(byte) +               // Statement or portal
                      name.Length + sizeof(byte);  // Statement or portal name plus null terminator

            if (WriteBuffer.WriteSpaceLeft < 10)
            {
                return(FlushAndWrite(len, type, name, async, cancellationToken));
            }

            Write(len, type, name);
            return(Task.CompletedTask);

            async Task FlushAndWrite(int len, StatementOrPortal type, string name, bool async, CancellationToken cancellationToken)
            {
                await Flush(async, cancellationToken);

                Debug.Assert(len <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length {len} which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write(len, type, name);
            }

            void Write(int len, StatementOrPortal type, string name)
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Close);
                WriteBuffer.WriteInt32(len - 1);
                WriteBuffer.WriteByte((byte)type);
                WriteBuffer.WriteNullTerminatedString(name);
            }
        }
        internal Task WriteSync(bool async, CancellationToken cancellationToken = default)
        {
            const int len = sizeof(byte) +  // Message code
                            sizeof(int);    // Length

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                return(FlushAndWrite(async, cancellationToken));
            }

            Write();
            return(Task.CompletedTask);

            async Task FlushAndWrite(bool async, CancellationToken cancellationToken)
            {
                await Flush(async, cancellationToken);

                Debug.Assert(len <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length {len} which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write();
            }

            void Write()
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Sync);
                WriteBuffer.WriteInt32(len - 1);
            }
        }
        internal async Task WriteSASLInitialResponse(string mechanism, byte[] initialResponse, bool async, CancellationToken cancellationToken = default)
        {
            var len = sizeof(byte) +                                                // Message code
                      sizeof(int) +                                                 // Length
                      PGUtil.UTF8Encoding.GetByteCount(mechanism) + sizeof(byte) +  // Mechanism plus null terminator
                      sizeof(int) +                                                 // Initial response length
                      (initialResponse?.Length ?? 0);                               // Initial response payload

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                await WriteBuffer.Flush(async, cancellationToken);
            }

            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(len - 1);

            WriteBuffer.WriteString(mechanism);
            WriteBuffer.WriteByte(0);   // null terminator
            if (initialResponse == null)
            {
                WriteBuffer.WriteInt32(-1);
            }
            else
            {
                WriteBuffer.WriteInt32(initialResponse.Length);
                WriteBuffer.WriteBytes(initialResponse);
            }
        }
Ejemplo n.º 7
0
        public override bool Write(ref DirectBuffer directBuf)
        {
            if (_lexemePos == -1)
            {
                if (_writeBuf.WriteSpaceLeft < 4)
                {
                    return(false);
                }
                _writeBuf.WriteInt32(_value.Count);
                _lexemePos = 0;
            }

            for (; _lexemePos < _value.Count; _lexemePos++)
            {
                if (_writeBuf.WriteSpaceLeft < MaxSingleLexemeBytes)
                {
                    return(false);
                }

                _writeBuf.WriteString(_value[_lexemePos].Text);
                _writeBuf.WriteByte(0);
                _writeBuf.WriteInt16(_value[_lexemePos].Count);
                for (var i = 0; i < _value[_lexemePos].Count; i++)
                {
                    _writeBuf.WriteInt16(_value[_lexemePos][i]._val);
                }
            }

            return(true);
        }
        internal Task WriteExecute(int maxRows, bool async, CancellationToken cancellationToken = default)
        {
            // Note: non-empty portal currently not supported

            const int len = sizeof(byte) +       // Message code
                            sizeof(int) +        // Length
                            sizeof(byte) +       // Null-terminated portal name (always empty for now)
                            sizeof(int);         // Max number of rows

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                return(FlushAndWrite(maxRows, async, cancellationToken));
            }

            Write(maxRows);
            return(Task.CompletedTask);

            async Task FlushAndWrite(int maxRows, bool async, CancellationToken cancellationToken)
            {
                await Flush(async, cancellationToken);

                Debug.Assert(10 <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length 10 which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write(maxRows);
            }

            void Write(int maxRows)
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Execute);
                WriteBuffer.WriteInt32(len - 1);
                WriteBuffer.WriteByte(0);   // Portal is always empty for now
                WriteBuffer.WriteInt32(maxRows);
            }
        }
        internal void WriteStartup(Dictionary <string, string> parameters)
        {
            var len = sizeof(int) +  // Length
                      sizeof(int) +  // Protocol version
                      sizeof(byte);  // Trailing zero byte

            foreach (var kvp in parameters)
            {
                len += PGUtil.UTF8Encoding.GetByteCount(kvp.Key) + 1 +
                       PGUtil.UTF8Encoding.GetByteCount(kvp.Value) + 1;
            }

            // Should really never happen, just in case
            if (len > WriteBuffer.Size)
            {
                throw new Exception("Startup message bigger than buffer");
            }

            WriteBuffer.WriteInt32(len);
            WriteBuffer.WriteInt16(ProtocolVersion.MAJOR);
            WriteBuffer.WriteInt16(ProtocolVersion.MINOR);

            foreach (var kv in parameters)
            {
                WriteBuffer.WriteString(kv.Key);
                WriteBuffer.WriteByte(0);
                WriteBuffer.WriteString(kv.Value);
                WriteBuffer.WriteByte(0);
            }

            WriteBuffer.WriteByte(0);
        }
Ejemplo n.º 10
0
        protected override async Task Write(object value, WriteBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter,
                                            bool async, CancellationToken cancellationToken)
        {
            var vector = (NpgsqlTsVector)value;

            if (buf.WriteSpaceLeft < 4)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteInt32(vector.Count);

            foreach (NpgsqlTsVector.Lexeme lexeme in vector)
            {
                if (buf.WriteSpaceLeft < MaxSingleLexemeBytes)
                {
                    await buf.Flush(async, cancellationToken);
                }

                buf.WriteString(lexeme.Text);
                buf.WriteByte(0);
                buf.WriteInt16(lexeme.Count);
                for (var i = 0; i < lexeme.Count; i++)
                {
                    buf.WriteInt16(lexeme[i].Value);
                }
            }
        }
Ejemplo n.º 11
0
 public override void Write(object value, WriteBuffer buf, NpgsqlParameter parameter)
 {
     if (parameter?.ConvertedValue != null)
     {
         value = parameter.ConvertedValue;
     }
     buf.WriteByte(((bool)value) ? (byte)1 : (byte)0);
 }
Ejemplo n.º 12
0
        internal override void WriteFully(WriteBuffer buf)
        {
            buf.WriteByte(Code);
            buf.WriteInt32(Length - 1);

            buf.WriteString(_mechanism);
            buf.WriteByte(0);   // null terminator
            if (_initialResponse == null)
            {
                buf.WriteInt32(-1);
            }
            else
            {
                buf.WriteInt32(_initialResponse.Length);
                buf.WriteBytes(_initialResponse);
            }
        }
Ejemplo n.º 13
0
 async Task WriteBool(bool b, WriteBuffer buf, bool async, CancellationToken cancellationToken)
 {
     if (buf.WriteSpaceLeft < 5)
     {
         await buf.Flush(async, cancellationToken);
     }
     buf.WriteInt32(1);
     buf.WriteByte(b ? (byte)0x80 : (byte)0);
 }
Ejemplo n.º 14
0
 protected override async Task Write(object value, WriteBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter,
                                     bool async, CancellationToken cancellationToken)
 {
     if (buf.WriteSpaceLeft < 1)
     {
         await buf.Flush(async, cancellationToken);
     }
     buf.WriteByte(JsonbProtocolVersion);
     await base.Write(value, buf, lengthCache, parameter, async, cancellationToken);
 }
Ejemplo n.º 15
0
        internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            Debug.Assert(Statement != null && Statement.All(c => c < 128));

            var queryByteLen = _encoding.GetByteCount(Query);

            if (buf.WriteSpaceLeft < 1 + 4 + Statement.Length + 1)
            {
                await buf.Flush(async, cancellationToken);
            }

            var messageLength =
                1 +                         // Message code
                4 +                         // Length
                Statement.Length +
                1 +                         // Null terminator
                queryByteLen +
                1 +                         // Null terminator
                2 +                         // Number of parameters
                ParameterTypeOIDs.Count * 4;

            buf.WriteByte(Code);
            buf.WriteInt32(messageLength - 1);
            buf.WriteNullTerminatedString(Statement);

            await buf.WriteString(Query, queryByteLen, async, cancellationToken);

            if (buf.WriteSpaceLeft < 1 + 2)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteByte(0); // Null terminator for the query
            buf.WriteInt16((short)ParameterTypeOIDs.Count);

            foreach (var t in ParameterTypeOIDs)
            {
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt32((int)t);
            }
        }
Ejemplo n.º 16
0
        internal override void WriteFully(WriteBuffer buf)
        {
            Contract.Requires(Portal != null && Portal.All(c => c < 128));

            var portalNameBytes = Portal == "" ? PGUtil.EmptyBuffer : Encoding.ASCII.GetBytes(Portal);
            buf.WriteByte(Code);
            buf.WriteInt32(Length - 1);
            buf.WriteBytesNullTerminated(portalNameBytes);
            buf.WriteInt32(MaxRows);
        }
Ejemplo n.º 17
0
        internal override void WriteFully(WriteBuffer buf)
        {
            Contract.Requires(Portal != null && Portal.All(c => c < 128));

            var portalNameBytes = Portal == "" ? PGUtil.EmptyBuffer : Encoding.ASCII.GetBytes(Portal);

            buf.WriteByte(Code);
            buf.WriteInt32(Length - 1);
            buf.WriteBytesNullTerminated(portalNameBytes);
            buf.WriteInt32(MaxRows);
        }
Ejemplo n.º 18
0
    internal async Task WriteParse(string sql, string statementName, List <NpgsqlParameter> inputParameters, bool async, CancellationToken cancellationToken = default)
    {
        Debug.Assert(statementName.All(c => c < 128));

        int queryByteLen;

        try
        {
            queryByteLen = TextEncoding.GetByteCount(sql);
        }
        catch (Exception e)
        {
            Break(e);
            throw;
        }

        if (WriteBuffer.WriteSpaceLeft < 1 + 4 + statementName.Length + 1)
        {
            await Flush(async, cancellationToken);
        }

        var messageLength =
            sizeof(byte) +                        // Message code
            sizeof(int) +                         // Length
            statementName.Length +                // Statement name
            sizeof(byte) +                        // Null terminator for the statement name
            queryByteLen + sizeof(byte) +         // SQL query length plus null terminator
            sizeof(ushort) +                      // Number of parameters
            inputParameters.Count * sizeof(int);  // Parameter OIDs

        WriteBuffer.WriteByte(FrontendMessageCode.Parse);
        WriteBuffer.WriteInt32(messageLength - 1);
        WriteBuffer.WriteNullTerminatedString(statementName);

        await WriteBuffer.WriteString(sql, queryByteLen, async, cancellationToken);

        if (WriteBuffer.WriteSpaceLeft < 1 + 2)
        {
            await Flush(async, cancellationToken);
        }
        WriteBuffer.WriteByte(0); // Null terminator for the query
        WriteBuffer.WriteUInt16((ushort)inputParameters.Count);

        foreach (var p in inputParameters)
        {
            if (WriteBuffer.WriteSpaceLeft < 4)
            {
                await Flush(async, cancellationToken);
            }

            WriteBuffer.WriteInt32((int)p.Handler !.PostgresType.OID);
        }
    }
Ejemplo n.º 19
0
        internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            if (buf.WriteSpaceLeft < 1 + 4)
            {
                await buf.Flush(async, cancellationToken);
            }
            var queryByteLen = _encoding.GetByteCount(_query);

            buf.WriteByte(Code);
            buf.WriteInt32(4 +            // Message length (including self excluding code)
                           queryByteLen + // Query byte length
                           1);            // Null terminator

            await buf.WriteString(_query, queryByteLen, async, cancellationToken);

            if (buf.WriteSpaceLeft < 1)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteByte(0);
        }
Ejemplo n.º 20
0
        internal override bool Write(WriteBuffer buf)
        {
            if (_charPos == -1)
            {
                // Start new query
                if (buf.WriteSpaceLeft < 1 + 4)
                {
                    return(false);
                }
                _charPos = 0;
                var queryByteLen = _encoding.GetByteCount(_query);
                _queryChars = _query.ToCharArray();
                buf.WriteByte(Code);
                buf.WriteInt32(4 +            // Message length (including self excluding code)
                               queryByteLen + // Query byte length
                               1);            // Null terminator
            }

            if (_charPos < _queryChars.Length)
            {
                int  charsUsed;
                bool completed;
                buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                       out charsUsed, out completed);
                _charPos += charsUsed;
                if (!completed)
                {
                    return(false);
                }
            }

            if (buf.WriteSpaceLeft < 1)
            {
                return(false);
            }
            buf.WriteByte(0);

            _charPos = -1;
            return(true);
        }
Ejemplo n.º 21
0
        internal override void WriteFully(WriteBuffer buf)
        {
            buf.WriteInt32(_length);
            buf.WriteInt32(ProtocolVersion3);

            foreach (var kv in _parameters)
            {
                buf.WriteBytesNullTerminated(kv.Key);
                buf.WriteBytesNullTerminated(kv.Value);
            }

            buf.WriteByte(0);
        }
Ejemplo n.º 22
0
    internal async Task WriteCopyDone(bool async, CancellationToken cancellationToken = default)
    {
        const int len = sizeof(byte) +   // Message code
                        sizeof(int);     // Length

        if (WriteBuffer.WriteSpaceLeft < len)
        {
            await Flush(async, cancellationToken);
        }

        WriteBuffer.WriteByte(FrontendMessageCode.CopyDone);
        WriteBuffer.WriteInt32(len - 1);
    }
Ejemplo n.º 23
0
        internal override void WriteFully(WriteBuffer buf)
        {
            buf.WriteInt32(_length);
            buf.WriteInt32(ProtocolVersion3);

            foreach (var kv in _parameters)
            {
                buf.WriteBytesNullTerminated(kv.Key);
                buf.WriteBytesNullTerminated(kv.Value);
            }

            buf.WriteByte(0);
        }
Ejemplo n.º 24
0
    internal void WriteTerminate()
    {
        const int len = sizeof(byte) +  // Message code
                        sizeof(int);    // Length

        if (WriteBuffer.WriteSpaceLeft < len)
        {
            Flush(false).GetAwaiter().GetResult();
        }

        WriteBuffer.WriteByte(FrontendMessageCode.Terminate);
        WriteBuffer.WriteInt32(len - 1);
    }
Ejemplo n.º 25
0
        public override bool Write(ref DirectBuffer directBuf)
        {
            switch (_state)
            {
            case State.Flags:
                if (_writeBuf.WriteSpaceLeft < 1)
                {
                    return(false);
                }
                _writeBuf.WriteByte((byte)_value.Flags);
                if (_value.IsEmpty)
                {
                    CleanupState();
                    return(true);
                }
                goto case State.LowerBound;

            case State.LowerBound:
                _state = State.LowerBound;
                if (_value.LowerBoundInfinite)
                {
                    goto case State.UpperBound;
                }

                if (!WriteSingleElement(_value.LowerBound, ref directBuf))
                {
                    return(false);
                }
                goto case State.UpperBound;

            case State.UpperBound:
                _state = State.UpperBound;
                if (_value.UpperBoundInfinite)
                {
                    CleanupState();
                    return(true);
                }
                if (!WriteSingleElement(_value.UpperBound, ref directBuf))
                {
                    return(false);
                }
                CleanupState();
                return(true);

            default:
                throw PGUtil.ThrowIfReached();
            }
        }
Ejemplo n.º 26
0
    internal async Task WriteCopyFail(bool async, CancellationToken cancellationToken = default)
    {
        // Note: error message not supported for now

        const int len = sizeof(byte) +  // Message code
                        sizeof(int) +   // Length
                        sizeof(byte);   // Error message is always empty (only a null terminator)

        if (WriteBuffer.WriteSpaceLeft < len)
        {
            await Flush(async, cancellationToken);
        }

        WriteBuffer.WriteByte(FrontendMessageCode.CopyFail);
        WriteBuffer.WriteInt32(len - 1);
        WriteBuffer.WriteByte(0);   // Error message is always empty (only a null terminator)
    }
Ejemplo n.º 27
0
 public override bool Write(ref DirectBuffer directBuf)
 {
     if (!_handledVersion)
     {
         if (_writeBuf.WriteSpaceLeft < 1)
         {
             return(false);
         }
         _writeBuf.WriteByte(JsonbProtocolVersion);
         _handledVersion = true;
     }
     if (!_textHandler.Write(ref directBuf))
     {
         return(false);
     }
     _writeBuf = null;
     return(true);
 }
Ejemplo n.º 28
0
        internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            if (buf.WriteSpaceLeft < 1 + 5)
            {
                await buf.Flush(async);
            }
            buf.WriteByte(Code);
            buf.WriteInt32(4 + PayloadLength);

            if (PayloadLength <= buf.WriteSpaceLeft)
            {
                // The entire array fits in our buffer, copy it into the buffer as usual.
                buf.WriteBytes(Payload, PayloadOffset, Payload.Length);
                return;
            }

            await buf.Flush(async);

            buf.DirectWrite(Payload, PayloadOffset, PayloadLength);
        }
Ejemplo n.º 29
0
    internal async Task WritePassword(byte[] payload, int offset, int count, bool async, CancellationToken cancellationToken = default)
    {
        if (WriteBuffer.WriteSpaceLeft < sizeof(byte) + sizeof(int))
        {
            await WriteBuffer.Flush(async, cancellationToken);
        }
        WriteBuffer.WriteByte(FrontendMessageCode.Password);
        WriteBuffer.WriteInt32(sizeof(int) + count);

        if (count <= WriteBuffer.WriteSpaceLeft)
        {
            // The entire array fits in our WriteBuffer, copy it into the WriteBuffer as usual.
            WriteBuffer.WriteBytes(payload, offset, count);
            return;
        }

        await WriteBuffer.Flush(async, cancellationToken);

        await WriteBuffer.DirectWrite(new ReadOnlyMemory <byte>(payload, offset, count), async, cancellationToken);
    }
Ejemplo n.º 30
0
        protected override async Task Write(object value, WriteBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter,
                                            bool async, CancellationToken cancellationToken)
        {
            var path = (NpgsqlPath)value;

            if (buf.WriteSpaceLeft < 5)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteByte((byte)(path.Open ? 0 : 1));
            buf.WriteInt32(path.Count);

            foreach (var p in path)
            {
                if (buf.WriteSpaceLeft < 16)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteDouble(p.X);
                buf.WriteDouble(p.Y);
            }
        }
Ejemplo n.º 31
0
        protected override async Task Write(object value, WriteBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter,
                                            bool async, CancellationToken cancellationToken)
        {
            var range = (NpgsqlRange <TElement>)value;

            if (buf.WriteSpaceLeft < 1)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteByte((byte)range.Flags);
            if (range.IsEmpty)
            {
                return;
            }
            if (!range.LowerBoundInfinite)
            {
                await ElementHandler.WriteWithLength(range.LowerBound, buf, lengthCache, null, async, cancellationToken);
            }
            if (!range.UpperBoundInfinite)
            {
                await ElementHandler.WriteWithLength(range.UpperBound, buf, lengthCache, null, async, cancellationToken);
            }
        }
Ejemplo n.º 32
0
    internal async Task WriteQuery(string sql, bool async, CancellationToken cancellationToken = default)
    {
        var queryByteLen = TextEncoding.GetByteCount(sql);

        if (WriteBuffer.WriteSpaceLeft < 1 + 4)
        {
            await Flush(async, cancellationToken);
        }

        WriteBuffer.WriteByte(FrontendMessageCode.Query);
        WriteBuffer.WriteInt32(
            sizeof(int) +         // Message length (including self excluding code)
            queryByteLen +        // Query byte length
            sizeof(byte));        // Null terminator

        await WriteBuffer.WriteString(sql, queryByteLen, async, cancellationToken);

        if (WriteBuffer.WriteSpaceLeft < 1)
        {
            await Flush(async, cancellationToken);
        }
        WriteBuffer.WriteByte(0);  // Null terminator
    }
Ejemplo n.º 33
0
 internal override void WriteFully(WriteBuffer buf)
 {
     buf.WriteByte(Code);
     buf.WriteInt32(4);
 }
Ejemplo n.º 34
0
 internal override void WriteFully(WriteBuffer buf)
 {
     buf.WriteByte(Code);
     buf.WriteInt32(Length - 1);
     buf.WriteBytes(Password, 0, Password.Length);
 }
Ejemplo n.º 35
0
    internal async Task WriteBind(
        List <NpgsqlParameter> parameters,
        string portal,
        string statement,
        bool allResultTypesAreUnknown,
        bool[]?unknownResultTypeList,
        bool async,
        CancellationToken cancellationToken = default)
    {
        Debug.Assert(statement.All(c => c < 128));
        Debug.Assert(portal.All(c => c < 128));

        var headerLength =
            sizeof(byte) +                        // Message code
            sizeof(int) +                         // Message length
            sizeof(byte) +                        // Portal is always empty (only a null terminator)
            statement.Length + sizeof(byte) +     // Statement name plus null terminator
            sizeof(ushort);                       // Number of parameter format codes that follow

        if (WriteBuffer.WriteSpaceLeft < headerLength)
        {
            Debug.Assert(WriteBuffer.Size >= headerLength, "Write buffer too small for Bind header");
            await Flush(async, cancellationToken);
        }

        var formatCodesSum = 0;
        var paramsLength   = 0;

        for (var paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
        {
            var param = parameters[paramIndex];
            formatCodesSum += (int)param.FormatCode;
            param.LengthCache?.Rewind();
            paramsLength += param.ValidateAndGetLength();
        }

        var formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == parameters.Count ? 1 : parameters.Count;

        var messageLength = headerLength +
                            sizeof(short) * formatCodeListLength +                  // List of format codes
                            sizeof(short) +                                         // Number of parameters
                            sizeof(int) * parameters.Count +                        // Parameter lengths
                            paramsLength +                                          // Parameter values
                            sizeof(short) +                                         // Number of result format codes
                            sizeof(short) * (unknownResultTypeList?.Length ?? 1);   // Result format codes

        WriteBuffer.WriteByte(FrontendMessageCode.Bind);
        WriteBuffer.WriteInt32(messageLength - 1);
        Debug.Assert(portal == string.Empty);
        WriteBuffer.WriteByte(0);  // Portal is always empty

        WriteBuffer.WriteNullTerminatedString(statement);
        WriteBuffer.WriteInt16(formatCodeListLength);

        // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
        if (formatCodeListLength == 1)
        {
            if (WriteBuffer.WriteSpaceLeft < 2)
            {
                await Flush(async, cancellationToken);
            }
            WriteBuffer.WriteInt16((short)FormatCode.Binary);
        }
        else if (formatCodeListLength > 1)
        {
            for (var paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
            {
                if (WriteBuffer.WriteSpaceLeft < 2)
                {
                    await Flush(async, cancellationToken);
                }
                WriteBuffer.WriteInt16((short)parameters[paramIndex].FormatCode);
            }
        }

        if (WriteBuffer.WriteSpaceLeft < 2)
        {
            await Flush(async, cancellationToken);
        }

        WriteBuffer.WriteUInt16((ushort)parameters.Count);

        for (var paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
        {
            var param = parameters[paramIndex];
            param.LengthCache?.Rewind();
            await param.WriteWithLength(WriteBuffer, async, cancellationToken);
        }

        if (unknownResultTypeList != null)
        {
            if (WriteBuffer.WriteSpaceLeft < 2 + unknownResultTypeList.Length * 2)
            {
                await Flush(async, cancellationToken);
            }
            WriteBuffer.WriteInt16(unknownResultTypeList.Length);
            foreach (var t in unknownResultTypeList)
            {
                WriteBuffer.WriteInt16(t ? 0 : 1);
            }
        }
        else
        {
            if (WriteBuffer.WriteSpaceLeft < 4)
            {
                await Flush(async, cancellationToken);
            }
            WriteBuffer.WriteInt16(1);
            WriteBuffer.WriteInt16(allResultTypesAreUnknown ? 0 : 1);
        }
    }
Ejemplo n.º 36
0
        bool Write(PostgisGeometry geom)
        {
            if (_newGeom & _icol.Count == 0)
            {
                if (geom.SRID == 0)
                {
                    if (_writeBuf.WriteSpaceLeft < 5)
                    {
                        return(false);
                    }
                    _writeBuf.WriteByte(0); // We choose to ouput only XDR structure
                    _writeBuf.WriteInt32((int)geom.Identifier);
                }
                else
                {
                    if (_writeBuf.WriteSpaceLeft < 9)
                    {
                        return(false);
                    }
                    _writeBuf.WriteByte(0);
                    _writeBuf.WriteInt32((int)((uint)geom.Identifier | (uint)EwkbModifier.HasSRID));
                    _writeBuf.WriteInt32((int)geom.SRID);
                }
                _newGeom = false;
            }
            switch (geom.Identifier)
            {
            case WkbIdentifier.Point:
                if (_writeBuf.WriteSpaceLeft < 16)
                {
                    return(false);
                }
                var p = (PostgisPoint)geom;
                _writeBuf.WriteDouble(p.X);
                _writeBuf.WriteDouble(p.Y);
                return(true);

            case WkbIdentifier.LineString:
                var l = (PostgisLineString)geom;
                if (_ipts == -1)
                {
                    if (_writeBuf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    _writeBuf.WriteInt32(l.PointCount);
                    _ipts = 0;
                }
                for (; _ipts < l.PointCount; _ipts++)
                {
                    if (_writeBuf.WriteSpaceLeft < 16)
                    {
                        return(false);
                    }
                    _writeBuf.WriteDouble(l[_ipts].X);
                    _writeBuf.WriteDouble(l[_ipts].Y);
                }
                return(true);

            case WkbIdentifier.Polygon:
                var pol = (PostgisPolygon)geom;
                if (_irng == -1)
                {
                    if (_writeBuf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    _writeBuf.WriteInt32(pol.RingCount);
                    _irng = 0;
                }
                for (; _irng < pol.RingCount; _irng++)
                {
                    if (_ipts == -1)
                    {
                        if (_writeBuf.WriteSpaceLeft < 4)
                        {
                            return(false);
                        }
                        _writeBuf.WriteInt32(pol[_irng].Length);
                        _ipts = 0;
                    }
                    for (; _ipts < pol[_irng].Length; _ipts++)
                    {
                        if (_writeBuf.WriteSpaceLeft < 16)
                        {
                            return(false);
                        }
                        _writeBuf.WriteDouble(pol[_irng][_ipts].X);
                        _writeBuf.WriteDouble(pol[_irng][_ipts].Y);
                    }
                    _ipts = -1;
                }
                return(true);

            case WkbIdentifier.MultiPoint:
                var mp = (PostgisMultiPoint)geom;
                if (_ipts == -1)
                {
                    if (_writeBuf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    _writeBuf.WriteInt32(mp.PointCount);
                    _ipts = 0;
                }
                for (; _ipts < mp.PointCount; _ipts++)
                {
                    if (_writeBuf.WriteSpaceLeft < 21)
                    {
                        return(false);
                    }
                    _writeBuf.WriteByte(0);
                    _writeBuf.WriteInt32((int)WkbIdentifier.Point);
                    _writeBuf.WriteDouble(mp[_ipts].X);
                    _writeBuf.WriteDouble(mp[_ipts].Y);
                }
                return(true);

            case WkbIdentifier.MultiLineString:
                var ml = (PostgisMultiLineString)geom;
                if (_irng == -1)
                {
                    if (_writeBuf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    _writeBuf.WriteInt32(ml.LineCount);
                    _irng = 0;
                }
                for (; _irng < ml.LineCount; _irng++)
                {
                    if (_ipts == -1)
                    {
                        if (_writeBuf.WriteSpaceLeft < 9)
                        {
                            return(false);
                        }
                        _writeBuf.WriteByte(0);
                        _writeBuf.WriteInt32((int)WkbIdentifier.LineString);
                        _writeBuf.WriteInt32(ml[_irng].PointCount);
                        _ipts = 0;
                    }
                    for (; _ipts < ml[_irng].PointCount; _ipts++)
                    {
                        if (_writeBuf.WriteSpaceLeft < 16)
                        {
                            return(false);
                        }
                        _writeBuf.WriteDouble(ml[_irng][_ipts].X);
                        _writeBuf.WriteDouble(ml[_irng][_ipts].Y);
                    }
                    _ipts = -1;
                }
                return(true);

            case WkbIdentifier.MultiPolygon:
                var mpl = (PostgisMultiPolygon)geom;
                if (_ipol == -1)
                {
                    if (_writeBuf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    _writeBuf.WriteInt32(mpl.PolygonCount);
                    _ipol = 0;
                }
                for (; _ipol < mpl.PolygonCount; _ipol++)
                {
                    if (_irng == -1)
                    {
                        if (_writeBuf.WriteSpaceLeft < 9)
                        {
                            return(false);
                        }
                        _writeBuf.WriteByte(0);
                        _writeBuf.WriteInt32((int)WkbIdentifier.Polygon);
                        _writeBuf.WriteInt32(mpl[_ipol].RingCount);
                        _irng = 0;
                    }
                    for (; _irng < mpl[_ipol].RingCount; _irng++)
                    {
                        if (_ipts == -1)
                        {
                            if (_writeBuf.WriteSpaceLeft < 4)
                            {
                                return(false);
                            }
                            _writeBuf.WriteInt32(mpl[_ipol][_irng].Length);
                            _ipts = 0;
                        }
                        for (; _ipts < mpl[_ipol][_irng].Length; _ipts++)
                        {
                            if (_writeBuf.WriteSpaceLeft < 16)
                            {
                                return(false);
                            }
                            _writeBuf.WriteDouble(mpl[_ipol][_irng][_ipts].X);
                            _writeBuf.WriteDouble(mpl[_ipol][_irng][_ipts].Y);
                        }
                        _ipts = -1;
                    }
                    _irng = -1;
                }
                _ipol = -1;
                return(true);

            case WkbIdentifier.GeometryCollection:
                var coll = (PostgisGeometryCollection)geom;
                if (_icol.Count == 0)
                {
                    if (_writeBuf.WriteSpaceLeft < 4)
                    {
                        return(false);
                    }
                    _writeBuf.WriteInt32(coll.GeometryCount);
                    _newGeom = true;
                }

                for (var i = _icol.Count > 0 ? _icol.Pop() : 0; i < coll.GeometryCount; i++)
                {
                    if (!Write(coll[i]))
                    {
                        _icol.Push(i);
                        return(false);
                    }
                    Reset();
                }
                return(true);

            default:
                throw new InvalidOperationException("Unknown Postgis identifier.");
            }
        }
Ejemplo n.º 37
0
 internal override void WriteFully(WriteBuffer buf)
 {
     buf.WriteByte((byte)BackendMessageCode.CopyDone);
     buf.WriteInt32(4);
 }
Ejemplo n.º 38
0
        internal bool Write(WriteBuffer buf, ref DirectBuffer directBuf)
        {
            Contract.Requires(Statement != null && Statement.All(c => c < 128));
            Contract.Requires(Portal != null && Portal.All(c => c < 128));

            switch (_state)
            {
                case State.Header:
                    var formatCodesSum = InputParameters.Select(p => p.FormatCode).Sum(c => (int)c);
                    _formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == InputParameters.Count ? 1 : InputParameters.Count;
                    var headerLength =
                        1 +                        // Message code
                        4 +                        // Message length
                        Portal.Length + 1 +
                        Statement.Length + 1 +
                        2;                         // Number of parameter format codes that follow

                    if (buf.WriteSpaceLeft < headerLength)
                    {
                        Contract.Assume(buf.Size >= headerLength, "Buffer too small for Bind header");
                        return false;
                    }

                    foreach (var c in InputParameters.Select(p => p.LengthCache).Where(c => c != null))
                        c.Rewind();
                    var messageLength = headerLength +
                        2 * _formatCodeListLength + // List of format codes
                        2 +                         // Number of parameters
                        4 * InputParameters.Count +                                     // Parameter lengths
                        InputParameters.Select(p => p.ValidateAndGetLength()).Sum() +   // Parameter values
                        2 +                                                             // Number of result format codes
                        2 * (UnknownResultTypeList?.Length ?? 1);                       // Result format codes

                    buf.WriteByte(Code);
                    buf.WriteInt32(messageLength-1);
                    buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Portal));
                    buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Statement));
                    buf.WriteInt16(_formatCodeListLength);
                    _paramIndex = 0;

                    _state = State.ParameterFormatCodes;
                    goto case State.ParameterFormatCodes;

                case State.ParameterFormatCodes:
                    // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
                    if (_formatCodeListLength == 1)
                    {
                        if (buf.WriteSpaceLeft < 2)
                            return false;
                        buf.WriteInt16((short)FormatCode.Binary);
                    }
                    else if (_formatCodeListLength > 1)
                        for (; _paramIndex < InputParameters.Count; _paramIndex++)
                        {
                            if (buf.WriteSpaceLeft < 2)
                                return false;
                            buf.WriteInt16((short)InputParameters[_paramIndex].FormatCode);
                        }
                    _state = State.ParameterCount;
                    goto case State.ParameterCount;

                case State.ParameterCount:
                    if (buf.WriteSpaceLeft < 2)
                        return false;

                    buf.WriteInt16(InputParameters.Count);
                    _paramIndex = 0;

                    _state = State.ParameterValues;
                    goto case State.ParameterValues;

                case State.ParameterValues:
                    if (!WriteParameters(buf, ref directBuf))
                        return false;
                    _state = State.ResultFormatCodes;
                    goto case State.ResultFormatCodes;

                case State.ResultFormatCodes:
                    if (UnknownResultTypeList != null)
                    {
                        if (buf.WriteSpaceLeft < 2 + UnknownResultTypeList.Length * 2)
                            return false;
                        buf.WriteInt16(UnknownResultTypeList.Length);
                        foreach (var t in UnknownResultTypeList)
                            buf.WriteInt16(t ? 0 : 1);
                    }
                    else
                    {
                        if (buf.WriteSpaceLeft < 4)
                            return false;
                        buf.WriteInt16(1);
                        buf.WriteInt16(AllResultTypesAreUnknown ? 0 : 1);
                    }

                    _state = State.Done;
                    return true;

                default:
                    throw PGUtil.ThrowIfReached();
            }
        }
Ejemplo n.º 39
0
 internal override void WriteFully(WriteBuffer buf)
 {
     buf.WriteByte(Code);
     buf.WriteInt32(4);
 }
Ejemplo n.º 40
0
        internal override bool Write(WriteBuffer buf)
        {
            Contract.Requires(Statement != null);

            switch (_state)
            {
                case State.WroteNothing:
                    _statementNameBytes = Statement.Length == 0 ? PGUtil.EmptyBuffer : _encoding.GetBytes(Statement);
                    _queryLen = _encoding.GetByteCount(Query);
                    if (buf.WriteSpaceLeft < 1 + 4 + _statementNameBytes.Length + 1) {
                        return false;
                    }

                    var messageLength =
                        1 +                         // Message code
                        4 +                         // Length
                        _statementNameBytes.Length +
                        1 +                         // Null terminator
                        _queryLen +
                        1 +                         // Null terminator
                        2 +                         // Number of parameters
                        ParameterTypeOIDs.Count * 4;

                    buf.WriteByte(Code);
                    buf.WriteInt32(messageLength - 1);
                    buf.WriteBytesNullTerminated(_statementNameBytes);
                    goto case State.WroteHeader;

                case State.WroteHeader:
                    _state = State.WroteHeader;

                    if (_queryLen <= buf.WriteSpaceLeft) {
                        buf.WriteString(Query);
                        goto case State.WroteQuery;
                    }

                    if (_queryLen <= buf.Size) {
                        // String can fit entirely in an empty buffer. Flush and retry rather than
                        // going into the partial writing flow below (which requires ToCharArray())
                        return false;
                    }

                    _queryChars = Query.ToCharArray();
                    _charPos = 0;
                    goto case State.WritingQuery;

                case State.WritingQuery:
                    _state = State.WritingQuery;
                    int charsUsed;
                    bool completed;
                    buf.WriteStringChunked(_queryChars, _charPos, _queryChars.Length - _charPos, true,
                                           out charsUsed, out completed);
                    if (!completed)
                    {
                        _charPos += charsUsed;
                        return false;
                    }
                    goto case State.WroteQuery;

                case State.WroteQuery:
                    _state = State.WroteQuery;
                    if (buf.WriteSpaceLeft < 1 + 2) {
                        return false;
                    }
                    buf.WriteByte(0); // Null terminator for the query
                    buf.WriteInt16((short)ParameterTypeOIDs.Count);
                    goto case State.WritingParameterTypes;

                case State.WritingParameterTypes:
                    _state = State.WritingParameterTypes;
                    for (; _parameterTypePos < ParameterTypeOIDs.Count; _parameterTypePos++)
                    {
                        if (buf.WriteSpaceLeft < 4)
                        {
                            return false;
                        }
                        buf.WriteInt32((int)ParameterTypeOIDs[_parameterTypePos]);
                    }

                    _state = State.WroteAll;
                    return true;

                default:
                    throw PGUtil.ThrowIfReached();
            }
        }