private Boolean closed = false; // true when we are closed /// <summary> /// This opens a large object. /// If the object does not exist, then an NpgsqlException is thrown. /// </summary> /// <param name="fp">FastPath API for the connection to use.</param> /// <param name="oid">OID of the Large Object to open.</param> /// <param name="mode">Mode of opening the large object</param> public LargeObject(Fastpath fp, Int32 oid, Int32 mode) { this.fp = fp; this.oid = oid; FastpathArg[] args = new FastpathArg[2]; args[0] = new FastpathArg(oid); args[1] = new FastpathArg(mode); this.fd = fp.GetInteger("lo_open", args); }
private Boolean closed = false; // true when we are closed /* * This opens a large object. * * <p>If the object does not exist, then an NpgsqlException is thrown. * * @param fp FastPath API for the connection to use * @param oid of the Large Object to open * @param mode Mode of opening the large object * (defined in LargeObjectManager) * @exception NpgsqlException if a database-access error occurs. * @see org.postgresql.largeobject.LargeObjectManager */ public LargeObject(Fastpath fp, Int32 oid, Int32 mode) { this.fp = fp; this.oid = oid; FastpathArg[] args = new FastpathArg[2]; args[0] = new FastpathArg(oid); args[1] = new FastpathArg(mode); this.fd = fp.GetInteger("lo_open", args); }
/// <summary> /// This method closes the object. You must not call methods in this /// object after this is called. /// </summary> public void Close() { if (!closed) { // finally close FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(fd); fp.FastpathCall("lo_close", false, args); // true here as we dont care!! closed = true; } }
/// <summary> /// This convenience method assumes that the return value is an Integer. /// </summary> /// <param name="name">Function name.</param> /// <param name="args">Function arguments.</param> /// <returns>Array containing result</returns> public Byte[] GetData(String name, FastpathArg[] args) { return (Byte[]) FastpathCall(name, false, args); }
private Object FastpathV2(Int32 fnid, Boolean resulttype, FastpathArg[] args) { // added Oct 7 1998 to give us thread safety lock (stream) { // send the function call try { // 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding // that confuses the backend. The 0 terminates the command line. stream.WriteByte((Byte)70); stream.WriteByte((Byte)0); PGUtil.WriteInt32(stream,fnid); PGUtil.WriteInt32(stream,args.Length); for (Int32 i = 0;i < args.Length;i++) args[i].Send(stream); // This is needed, otherwise data can be lost stream.Flush(); } catch (IOException ioe) { //Should be sending exception as second arg. throw new Exception("postgresql.fp.send: " + ioe.ToString()); } // Now handle the result // Now loop, reading the results Object result = null; // our result String errorMessage = ""; Byte[] input_buffer = new Byte[512]; Int32 c; Boolean l_endQuery = false; while (!l_endQuery) { c = (Char)stream.ReadByte(); switch (c) { case 'A': // Asynchronous Notify //TODO: do something with this Int32 pid = PGUtil.ReadInt32(stream,input_buffer); String msg = 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); errorMessage += e.Message; break; //------------------------------ // Notice from backend case 'N': NpgsqlError notice = new NpgsqlError(conn.BackendProtocolVersion); notice.ReadFromStream(stream,conn.Connector.Encoding); errorMessage += notice.Message; break; case 'V': Char l_nextChar = (Char)stream.ReadByte(); if (l_nextChar == 'G') { Int32 sz = PGUtil.ReadInt32(stream,input_buffer); // Return an Integer if if (resulttype) result = PGUtil.ReadInt32(stream,input_buffer); else { Byte[] buf = new Byte[sz]; Int32 bytes_from_stream = 0; Int32 total_bytes_read = 0; Int32 size = sz; 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; } //There should be a trailing '0' Int32 l_endChar = (Char)stream.ReadByte(); } else { //it must have been a '0', thus no results } break; case 'Z': l_endQuery = true; break; default: throw new Exception("postgresql.fp.protocol " + c.ToString()); } } if ( errorMessage != null ) throw new Exception("postgresql.fp.error" + errorMessage); return result; } }
/* * Sets the current position within the object. * * <p>This is similar to the fseek() call in the standard C library. It * allows you to have random access to the large object. * * @param pos position within object * @param ref Either SEEK_SET, SEEK_CUR or SEEK_END * @exception NpgsqlException if a database-access error occurs. */ public void Seek(Int32 pos, Int32 refi) { FastpathArg[] args = new FastpathArg[3]; args[0] = new FastpathArg(fd); args[1] = new FastpathArg(pos); args[2] = new FastpathArg(refi); fp.FastpathCall("lo_lseek", false, args); }
/* * Reads some data from the object, and return as a byte[] array * * @param len number of bytes to read * @return byte[] array containing data read * @exception NpgsqlException if a database-access error occurs. */ public Byte[] Read(Int32 len) { // This is the original method, where the entire block (len bytes) // is retrieved in one go. FastpathArg[] args = new FastpathArg[2]; args[0] = new FastpathArg(fd); args[1] = new FastpathArg(len); return fp.GetData("loread", args); // This version allows us to break this down Int32o 4k blocks //if (len<=4048) { //// handle as before, return the whole block in one go //FastpathArg args[] = new FastpathArg[2]; //args[0] = new FastpathArg(fd); //args[1] = new FastpathArg(len); //return fp.getData("loread",args); //} else { //// return in 4k blocks //byte[] buf=new byte[len]; //int off=0; //while (len>0) { //int bs=4048; //len-=bs; //if (len<0) { //bs+=len; //len=0; //} //read(buf,off,bs); //off+=bs; //} //return buf; //} }
/* * This creates a large object, returning its OID * * @param mode a bitmask describing different attributes of the new object * @return oid of new object * @exception NpgsqlException on error */ public Int32 Create(Int32 mode) { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(mode); return(fp.GetInteger("lo_creat", args)); }
/// <summary> /// Report the current position within the object. /// </summary> /// <returns>The current position within the object.</returns> public Int32 Tell() { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(fd); return(fp.GetInteger("lo_tell", args)); }
/// <summary> /// Send a function call to the PostgreSQL backend. /// </summary> /// <param name="fnid">Function id.</param> /// <param name="resulttype">True if the result is an integer, false for other results.</param> /// <param name="args">FastpathArguments to pass to fastpath.</param> /// <returns>null if no data, Integer if an integer result, or byte[] otherwise.</returns> public Object FastpathCall(Int32 fnid, Boolean resulttype, FastpathArg[] args) { try { if (conn.BackendProtocolVersion == ProtocolVersion.Version3) { return FastpathV3(fnid, resulttype, args); } else { return FastpathV2(fnid, resulttype, args); } } catch (IOException) { conn.ClearPool(); throw new NpgsqlException("The Connection is broken."); } }
private Object FastpathV2(Int32 fnid, Boolean resulttype, FastpathArg[] args) { // added Oct 7 1998 to give us thread safety lock (stream) { // send the function call stream .WriteBytesNullTerminated((byte)ASCIIBytes.F) .WriteInt32(fnid) .WriteInt32(args.Length); for (Int32 i = 0; i < args.Length; i++) { args[i].Send(stream); } // This is needed, otherwise data can be lost stream.Flush(); // Now handle the result // Now loop, reading the results Object result = null; // our result String errorMessage = ""; Int32 c; Boolean l_endQuery = false; while (!l_endQuery) { c = (Char) stream.ReadByte(); switch (c) { case 'A': // Asynchronous Notify //TODO: do something with this Int32 pid = PGUtil.ReadInt32(stream); String msg = PGUtil.ReadString(stream); break; //------------------------------ // Error message returned case 'E': NpgsqlError e = new NpgsqlError(conn.BackendProtocolVersion, stream); errorMessage += e.Message; break; //------------------------------ // Notice from backend case 'N': NpgsqlError notice = new NpgsqlError(conn.BackendProtocolVersion, stream); errorMessage += notice.Message; break; case 'V': Char l_nextChar = (Char) stream.ReadByte(); if (l_nextChar == 'G') { Int32 sz = PGUtil.ReadInt32(stream); // Return an Integer if if (resulttype) { result = PGUtil.ReadInt32(stream); } else { Byte[] buf = new Byte[sz]; Int32 bytes_from_stream = 0; Int32 total_bytes_read = 0; Int32 size = sz; 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; } //There should be a trailing '0' Int32 l_endChar = (Char) stream.ReadByte(); } else { //it must have been a '0', thus no results } break; case 'Z': l_endQuery = true; break; default: throw new NpgsqlException(string.Format("postgresql.fp.protocol {0}", c)); } } if (errorMessage != null) { throw new NpgsqlException("postgresql.fp.error" + errorMessage); } return result; } }
/* * Reads some data from the object, and return as a byte[] array * * @param len number of bytes to read * @return byte[] array containing data read * @exception NpgsqlException if a database-access error occurs. */ public Byte[] Read(Int32 len) { // This is the original method, where the entire block (len bytes) // is retrieved in one go. FastpathArg[] args = new FastpathArg[2]; args[0] = new FastpathArg(fd); args[1] = new FastpathArg(len); return fp.GetData("loread", args); }
/// <summary> /// Send a function call to the PostgreSQL backend. /// </summary> /// <param name="fnid">Function id.</param> /// <param name="resulttype">True if the result is an integer, false for other results.</param> /// <param name="args">FastpathArguments to pass to fastpath.</param> /// <returns>null if no data, Integer if an integer result, or byte[] otherwise.</returns> public Object FastpathCall(Int32 fnid, Boolean resulttype, FastpathArg[] args) { try { return FastpathV3(fnid, resulttype, args); } catch (IOException) { conn.ClearPool(); throw new NpgsqlException("The Connection is broken."); } }
/* * Send a function call to the PostgreSQL backend * * @param fnid Function id * @param resulttype True if the result is an integer, false for other results * @param args FastpathArguments to pass to fastpath * @return null if no data, Integer if an integer result, or byte[] otherwise * @exception SQLException if a database-access error occurs. */ public Object FastpathCall(Int32 fnid, Boolean resulttype, FastpathArg[] args) { if (conn.BackendProtocolVersion == ProtocolVersion.Version3) { return FastpathV3(fnid, resulttype, args); } else { return FastpathV2(fnid, resulttype, args); } }
/// <summary> /// Send a function call to the PostgreSQL backend. /// </summary> /// <param name="fnid">Function id.</param> /// <param name="resulttype">True if the result is an integer, false for other results.</param> /// <param name="args">FastpathArguments to pass to fastpath.</param> /// <returns>null if no data, Integer if an integer result, or byte[] otherwise.</returns> public Object FastpathCall(Int32 fnid, Boolean resulttype, FastpathArg[] args) { try { return FastpathV3(fnid, resulttype, args); } catch (IOException) { conn.ClearPool(); throw; } }
/// <summary> /// This creates a large object, returning its OID. /// </summary> /// <returns>OID of new object.</returns> public Int32 Create() { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(READWRITE); return fp.GetInteger("lo_creat", args); }
/* * This creates a large object, returning its OID * * @param mode a bitmask describing different attributes of the new object * @return oid of new object */ /// <summary> /// This creates a large object, returning its OID. /// </summary> /// <param name="mode">Bitmask describing different attributes of the new object.</param> /// <returns>OID of new object.</returns> public Int32 Create(Int32 mode) { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(mode); return fp.GetInteger("lo_creat", args); }
/* * This creates a large object, returning its OID. * * <p>It defaults to READWRITE for the new object's attributes. * * @return oid of new object * @exception NpgsqlException on error */ public Int32 Create() { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(READWRITE); return(fp.GetInteger("lo_creat", args)); }
/// <summary> /// This deletes a large object. /// </summary> /// <param name="oid">OID describing object to delete.</param> public void Delete(Int32 oid) { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(oid); fp.FastpathCall("lo_unlink", false, args); }
/* * This deletes a large object. * * @param oid describing object to delete * @exception NpgsqlException on error */ public void Delete(Int32 oid) { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(oid); fp.FastpathCall("lo_unlink", false, args); }
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(ASCIIByteArrays.FunctionCallMessageCode) .WriteInt32(l_msgLen) .WriteInt32(fnid) .WriteInt16(1) .WriteInt16(1) .WriteInt16((short)args.Length); for (Int32 i = 0; i < args.Length; i++) { args[i].Send(stream); } stream.WriteInt16(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; while (!l_endQuery) { c = (Char) stream.ReadByte(); switch (c) { case 'A': // Asynchronous Notify Int32 msglen = stream.ReadInt32(); Int32 pid = stream.ReadInt32(); String msg = stream.ReadString(); stream.ReadString(); String param = stream.ReadString(); break; //------------------------------ // Error message returned case 'E': NpgsqlError e = new NpgsqlError(stream); throw new NpgsqlException(e.ToString()); //------------------------------ // Notice from backend case 'N': Int32 l_nlen = stream.ReadInt32(); conn.Connector.FireNotice(new NpgsqlError(stream)); break; case 'V': Int32 l_msgLen = stream.ReadInt32(); Int32 l_valueLen = stream.ReadInt32(); if (l_valueLen == -1) { //null value } else if (l_valueLen == 0) { result = new Byte[0]; } else { // Return an Integer if if (resulttype) { result = stream.ReadInt32(); } 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 (stream.ReadInt32() != 5) { throw new Exception("Received Z"); } //TODO: handle transaction status Char l_tStatus = (Char) stream.ReadByte(); l_endQuery = true; break; default: throw new Exception(string.Format("postgresql.fp.protocol received {0}", c)); } } if (error != null) { throw error; } return result; } }
/* * Writes an array to the object * * @param buf array to write * @exception NpgsqlException if a database-access error occurs. */ public void Write(Byte[] buf) { FastpathArg[] args = new FastpathArg[2]; args[0] = new FastpathArg(fd); args[1] = new FastpathArg(buf); fp.FastpathCall("lowrite", false, args); }
/// <summary> /// Send a function call to the PostgreSQL backend by name. /// Note: the mapping for the procedure name to function id needs to exist, /// usually to an earlier call to addfunction(). /// This is the prefered method to call, as function id's can/may change /// between versions of the backend. /// For an example of how this works, refer to NpgsqlTypes.LargeObject /// </summary> /// <param name="name">Function name.</param> /// <param name="resulttype">True if the result is an integer, false for other results.</param> /// <param name="args">FastpathArguments to pass to fastpath.</param> /// <returns>null if no data, Integer if an integer result, or byte[] otherwise.</returns> public Object FastpathCall(String name, Boolean resulttype, FastpathArg[] args) { return FastpathCall(GetID(name), resulttype, args); }
/* * @return the current position within the object * @exception NpgsqlException if a database-access error occurs. */ public Int32 Tell() { FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(fd); return fp.GetInteger("lo_tell", args); }
/// <summary> /// This convenience method assumes that the return value is an Integer. /// </summary> /// <param name="name">Function name.</param> /// <param name="args">Function arguments.</param> /// <returns>Integer result.</returns> public Int32 GetInteger(String name, FastpathArg[] args) { Int32 i = (Int32) FastpathCall(name, true, args); return i; }
/* * This method closes the object. You must not call methods in this * object after this is called. * @exception NpgsqlException if a database-access error occurs. */ public void Close() { if (!closed) { // finally close FastpathArg[] args = new FastpathArg[1]; args[0] = new FastpathArg(fd); fp.FastpathCall("lo_close", false, args); // true here as we dont care!! closed = true; } }
private Object FastpathV3(Int32 fnid, Boolean resulttype, FastpathArg[] args) { // give thread safety lock (stream) { // send the function call try { 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(); } catch (Exception ex) { throw new Exception(ex.ToString()); } // 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 Exception(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 Exception("Received Z" ); //TODO: handle transaction status Char l_tStatus = (Char)stream.ReadByte(); l_endQuery = true; break; default: throw new Exception("postgresql.fp.protocol received " + c.ToString()); } } if ( error != null ) throw error; return result; } }