/// <summary>
        /// Helper method that updates all child expressions or statements
        /// by setting their parent to the immediate parent
        /// </summary>
        /// <param name="self">The item to update.</param>
        public static void UpdateParents(this Statement self)
        {
            var parents = new Stack <ASTItem>();

            foreach (var n in self.All((item, type) =>
            {
                if (!(item is Statement || item is Expression))
                {
                    return(false);
                }

                if (type == VisitorState.Enter)
                {
                    if (item != self)
                    {
                        item.Parent = parents.Peek();
                    }
                    parents.Push(item);
                }
                else if (type == VisitorState.Leave)
                {
                    parents.Pop();
                }

                return(true);
            }))
            {
            }

            if (parents.Count != 0)
            {
                throw new Exception($"{nameof(UpdateParents)} is broken ...");
            }
        }
Beispiel #2
0
        internal override async Task Write(NpgsqlWriteBuffer buf, bool async)
        {
            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);
            }

            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);

            if (buf.WriteSpaceLeft < 1 + 2)
            {
                await buf.Flush(async);
            }
            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);
                }
                buf.WriteInt32((int)t);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Removes all <see cref="CaseGotoStatement"/>'s and inserts appropriate variables updates instead
        /// </summary>
        /// <returns>The statements without goto-statemtns.</returns>
        /// <param name="statement">The statements to update.</param>
        /// <param name="currentstate">The variable for the current state.</param>
        /// <param name="nextstate">The variable for the next clock state.</param>
        /// <param name="enumfields">The enum values for each state.</param>
        private Statement ReplaceGotoWithVariables(Statement statement, DataElement currentstate, DataElement nextstate, DataElement[] enumfields)
        {
            CaseGotoStatement current;

            while ((current = statement.All().OfType <CaseGotoStatement>().FirstOrDefault()) != null)
            {
                var fallThrough = current.FallThrough && current.CaseLabel < enumfields.Length;

                current.ReplaceWith(
                    new ExpressionStatement(
                        new AssignmentExpression(
                            new IdentifierExpression(fallThrough ? currentstate : nextstate),
                            new PrimitiveExpression(enumfields[current.CaseLabel % enumfields.Length].GetTarget().Name, enumfields[0].CecilType)
                            )
                        )
                    );
            }

            return(statement);
        }
Beispiel #4
0
        internal override bool Write(NpgsqlBuffer buf, ref byte[] directBuf)
        {
            Contract.Requires(Statement != null && Statement.All(c => c < 128));
            Contract.Requires(Portal != null && Portal.All(c => c < 128));

            switch (_state)
            {
            case State.WroteNothing:
                var formatCodesSum       = InputParameters.Select(p => p.FormatCode).Sum(c => (int)c);
                var formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == InputParameters.Count ? 1 : InputParameters.Count;

                var headerLength =
                    4 +                            // Message length
                    Portal.Length + 1 +
                    Statement.Length + 1 +
                    2 +                            // Number of parameter format codes that follow
                    2 * formatCodeListLength +     // List of format codes
                    2;                             // Number of parameters

                if (buf.WriteSpaceLeft < headerLength)
                {
                    if (buf.Size < headerLength)
                    {
                        throw new Exception("Buffer too small for Bind header");
                    }
                    return(false);
                }

                var messageLength = headerLength +
                                    4 * InputParameters.Count +                                             // Parameter lengths
                                    InputParameters.Select(p => p.BoundSize).Sum() +                        // Parameter values
                                    2 +                                                                     // Number of result format codes
                                    2 * (UnknownResultTypeList == null ? 1 : UnknownResultTypeList.Length); // Result format codes

                buf.WriteByte(Code);
                buf.WriteInt32(messageLength);
                buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Portal));
                buf.WriteBytesNullTerminated(Encoding.ASCII.GetBytes(Statement));

                // 0 implicitly means all-text, 1 means all binary, >1 means mix-and-match
                buf.WriteInt16(formatCodeListLength);
                if (formatCodeListLength == 1)
                {
                    buf.WriteInt16((short)FormatCode.Binary);
                }
                else if (formatCodeListLength > 1)
                {
                    foreach (var code in InputParameters.Select(p => p.FormatCode))
                    {
                        buf.WriteInt16((short)code);
                    }
                }

                buf.WriteInt16(InputParameters.Count);
                _state = State.WroteHeader;
                goto case State.WroteHeader;

            case State.WroteHeader:
                if (!WriteParameters(buf, ref directBuf))
                {
                    return(false);
                }
                _state = State.WroteParameters;
                goto case State.WroteParameters;

            case State.WroteParameters:
                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();
            }
        }
Beispiel #5
0
        internal override bool Write(NpgsqlBuffer buf, ref DirectBuffer directBuf)
        {
            Contract.Requires(Statement != null && Statement.All(c => c < 128));

            switch (_state)
            {
            case State.WroteNothing:
                _statementNameBytes = PGUtil.UTF8Encoding.GetBytes(Statement);
                _queryLen           = PGUtil.UTF8Encoding.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();
            }
        }
Beispiel #6
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);
                    }
                }

                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();
            }
        }
Beispiel #7
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);
            }
        }