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; }
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)); }
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); } }
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); }
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); } } }
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); }
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); } }
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); }
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); }
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); } }
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); }
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); } }
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); }
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); }
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); }
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); }
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); }
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(); } }
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) }
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); }
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); }
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); }
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); } }
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); } }
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 }
internal override void WriteFully(WriteBuffer buf) { buf.WriteByte(Code); buf.WriteInt32(4); }
internal override void WriteFully(WriteBuffer buf) { buf.WriteByte(Code); buf.WriteInt32(Length - 1); buf.WriteBytes(Password, 0, Password.Length); }
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); } }
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."); } }
internal override void WriteFully(WriteBuffer buf) { buf.WriteByte((byte)BackendMessageCode.CopyDone); buf.WriteInt32(4); }
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(); } }
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(); } }