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