Beispiel #1
0
    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);
        }
    }
Beispiel #2
0
        internal override void WriteFully(WriteBuffer buf)
        {
            Debug.Assert(Name != null && Name.All(c => c < 128));

            buf.WriteByte(Code);
            buf.WriteInt32(Length - 1);
            buf.WriteByte((byte)StatementOrPortal);
            buf.WriteNullTerminatedString(Name);
        }
Beispiel #3
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);
        }
    }
Beispiel #4
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);
            }
        }
Beispiel #5
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);
        }
    }
Beispiel #6
0
        internal override async Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            Debug.Assert(Statement != null && Statement.All(c => c < 128));
            Debug.Assert(Portal != null && Portal.All(c => c < 128));

            var headerLength =
                1 +                        // Message code
                4 +                        // Message length
                1 +                        // Portal is always empty (only a null terminator)
                Statement.Length + 1 +
                2;                         // Number of parameter format codes that follow

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

            var formatCodesSum = 0;
            var paramsLength   = 0;

            foreach (var p in InputParameters)
            {
                formatCodesSum += (int)p.FormatCode;
                p.LengthCache?.Rewind();
                paramsLength += p.ValidateAndGetLength();
            }

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

            var messageLength = headerLength +
                                2 * formatCodeListLength +                // List of format codes
                                2 +                                       // Number of parameters
                                4 * InputParameters.Count +               // Parameter lengths
                                paramsLength +                            // Parameter values
                                2 +                                       // Number of result format codes
                                2 * (UnknownResultTypeList?.Length ?? 1); // Result format codes

            buf.WriteByte(Code);
            buf.WriteInt32(messageLength - 1);
            Debug.Assert(Portal == string.Empty);
            buf.WriteByte(0);  // Portal is always empty

            buf.WriteNullTerminatedString(Statement);
            buf.WriteInt16(formatCodeListLength);

            // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
            if (formatCodeListLength == 1)
            {
                if (buf.WriteSpaceLeft < 2)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt16((short)FormatCode.Binary);
            }
            else if (formatCodeListLength > 1)
            {
                foreach (NpgsqlParameter p in InputParameters)
                {
                    if (buf.WriteSpaceLeft < 2)
                    {
                        await buf.Flush(async, cancellationToken);
                    }
                    buf.WriteInt16((short)p.FormatCode);
                }
            }

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

            buf.WriteInt16(InputParameters.Count);

            foreach (var param in InputParameters)
            {
                param.LengthCache?.Rewind();
                await param.WriteWithLength(buf, async, cancellationToken);
            }

            if (UnknownResultTypeList != null)
            {
                if (buf.WriteSpaceLeft < 2 + UnknownResultTypeList.Length * 2)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt16(UnknownResultTypeList.Length);
                foreach (var t in UnknownResultTypeList)
                {
                    buf.WriteInt16(t ? 0 : 1);
                }
            }
            else
            {
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt16(1);
                buf.WriteInt16(AllResultTypesAreUnknown ? 0 : 1);
            }
        }