示例#1
0
        private Object FastpathV3(Int32 fnid, Boolean resulttype, FastpathArg[] args)
        {
            // give  thread safety
            lock (stream)
            {
                // send the function call

                {
                    Int32 l_msgLen = 0;
                    l_msgLen += 16;
                    for (Int32 i = 0; i < args.Length; i++)
                    {
                        l_msgLen += args[i].SendSize();
                    }

                    stream.WriteByte((Byte)'F');
                    PGUtil.WriteInt32(stream, l_msgLen);
                    PGUtil.WriteInt32(stream, fnid);
                    PGUtil.WriteInt16(stream, 1);
                    PGUtil.WriteInt16(stream, 1);
                    PGUtil.WriteInt16(stream, (short)args.Length);

                    for (Int32 i = 0; i < args.Length; i++)
                    {
                        args[i].Send(stream);
                    }

                    PGUtil.WriteInt16(stream, 1);

                    // This is needed, otherwise data can be lost
                    stream.Flush();
                }


                // Now handle the result

                // Now loop, reading the results
                Object    result = null; // our result
                Exception error  = null;
                Int32     c;
                Boolean   l_endQuery   = false;
                Byte[]    input_buffer = new Byte[512];

                while (!l_endQuery)
                {
                    c = (Char)stream.ReadByte();

                    switch (c)
                    {
                    case 'A':   // Asynchronous Notify
                        Int32  msglen = PGUtil.ReadInt32(stream, input_buffer);
                        Int32  pid    = PGUtil.ReadInt32(stream, input_buffer);
                        String msg    = PGUtil.ReadString(stream, conn.Connector.Encoding);
                        PGUtil.ReadString(stream, conn.Connector.Encoding);
                        String param = PGUtil.ReadString(stream, conn.Connector.Encoding);

                        conn.Connector.CheckErrorsAndNotifications();
                        break;

                    //------------------------------
                    // Error message returned
                    case 'E':
                        NpgsqlError e = new NpgsqlError(conn.BackendProtocolVersion);
                        e.ReadFromStream(stream, conn.Connector.Encoding);
                        throw new NpgsqlException(e.ToString());

                    //------------------------------
                    // Notice from backend
                    case 'N':
                        Int32 l_nlen = PGUtil.ReadInt32(stream, input_buffer);

                        NpgsqlError e1 = new NpgsqlError(conn.BackendProtocolVersion);
                        e1.ReadFromStream(stream, conn.Connector.Encoding);
                        conn.Connector.Mediator.Errors.Add(e1);

                        break;

                    case 'V':
                        Int32 l_msgLen   = PGUtil.ReadInt32(stream, input_buffer);
                        Int32 l_valueLen = PGUtil.ReadInt32(stream, input_buffer);

                        if (l_valueLen == -1)
                        {
                            //null value
                        }
                        else if (l_valueLen == 0)
                        {
                            result = new Byte[0];
                        }
                        else
                        {
                            // Return an Integer if
                            if (resulttype)
                            {
                                result = PGUtil.ReadInt32(stream, input_buffer);
                            }
                            else
                            {
                                Byte[] buf = new Byte[l_valueLen];

                                Int32 bytes_from_stream = 0;
                                Int32 total_bytes_read  = 0;
                                Int32 size = l_valueLen;
                                do
                                {
                                    bytes_from_stream = stream.Read(buf, total_bytes_read, size);
                                    total_bytes_read += bytes_from_stream;
                                    size -= bytes_from_stream;
                                }while(size > 0);

                                result = buf;
                            }
                        }
                        break;

                    case 'Z':
                        //TODO: use size better
                        if (PGUtil.ReadInt32(stream, input_buffer) != 5)
                        {
                            throw new NpgsqlException("Received Z");
                        }
                        //TODO: handle transaction status
                        Char l_tStatus = (Char)stream.ReadByte();
                        l_endQuery = true;
                        break;

                    default:
                        throw new NpgsqlException("postgresql.fp.protocol received " + c.ToString());
                    }
                }

                if (error != null)
                {
                    throw error;
                }

                return(result);
            }
        }