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); }
/* * 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 { 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; while (!l_endQuery) { c = (Char)stream.ReadByte(); switch (c) { case 'A': // Asynchronous Notify Int32 msglen = PGUtil.ReadInt32(stream, buffer); Int32 pid = PGUtil.ReadInt32(stream, buffer); String msg = PGUtil.ReadString(stream, queue); PGUtil.ReadString(stream, queue); String param = PGUtil.ReadString(stream, queue); break; //------------------------------ // Error message returned case 'E': NpgsqlError e = new NpgsqlError(stream, buffer, queue); throw new NpgsqlException(e.ToString()); //------------------------------ // Notice from backend case 'N': Int32 l_nlen = PGUtil.ReadInt32(stream, buffer); conn.Connector.FireNotice(new NpgsqlError(stream, buffer, queue)); break; case 'V': Int32 l_msgLen = PGUtil.ReadInt32(stream, buffer); Int32 l_valueLen = PGUtil.ReadInt32(stream, 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, 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, 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(string.Format("postgresql.fp.protocol received {0}", c)); } } if (error != null) { throw error; } return result; } }
/* * 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); }
/* * 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)); }
/* * 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)); }
/* * 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); }
/* * This convenience method assumes that the return value is an Integer * @param name Function name * @param args Function arguments * @return byte[] array containing result * @exception NpgsqlException if a database-access error occurs or no result */ public Byte[] GetData(String name, FastpathArg[] args) { return (Byte[])FastpathCall(name, false, args); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * @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)); }
/* * 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 org.postgresql.largeobject.LargeObject * * @param name Function name * @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 NpgsqlException if name is unknown or if a database-access error * occurs. * @see org.postgresql.largeobject.LargeObject */ public Object FastpathCall(String name, Boolean resulttype, FastpathArg[] args) { return FastpathCall(GetID(name), resulttype, args); }
/* * This convenience method assumes that the return value is an Integer * @param name Function name * @param args Function arguments * @return integer result * @exception NpgsqlException if a database-access error occurs or no result */ public Int32 GetInteger(String name, FastpathArg[] args) { Int32 i = (Int32)FastpathCall(name, true, args); return i; }
/* * @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); }
/* * 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 NpgsqlException if a database-access error occurs. */ 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."); } }
/* * 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); }