示例#1
0
        public override void Write(object value, WriteBuffer buf, NpgsqlParameter parameter)
        {
            var tid = (NpgsqlTid)value;

            buf.WriteUInt32(tid.BlockNumber);
            buf.WriteUInt16(tid.OffsetNumber);
        }
示例#2
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);
        }
    }
示例#3
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);
        }
    }