My environment is Oracle 11g. I have a T_IMG table whose columns are an image frame, an image identifier, and an image hash calculated as SHA256. I want the image hash to be computed and inserted into the T_IMG table every time a row is inserted or updated in the T_IMG table. To do this, I use the T_IMG table before the trigger when inserting or updating the table, but it is difficult for me to access the blob column of the image inside the trigger.
CREATE TABLE TEST.T_IMG ( IDN VARCHAR2(18 BYTE) NOT NULL, IMG BLOB NOT NULL, IMGHASH VARCHAR2(128 BYTE) );
The SHA256 hash for strings and blobs is calculated using the following code, based on the example of Sean Stueber at http://seanstuber.wordpress.com/2012/03/22/using-java-to-extend-dbms_crypto/
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED sha2 AS import java.security.MessageDigest; import oracle.sql.*; public class sha2 { public static oracle.sql.RAW get_digest_string( String p_string, int p_bits ) throws Exception { MessageDigest v_md = MessageDigest.getInstance( "SHA-" + p_bits ); byte[] v_digest; v_digest = v_md.digest( p_string.getBytes( "UTF-8" ) ); return RAW.newRAW(v_digest); } public static oracle.sql.RAW get_digest_blob( oracle.sql.BLOB p_blob, int p_bits ) throws Exception { byte[] allBytesInBlob; allBytesInBlob = p_blob.getBytes(1, (int) p_blob.length()); MessageDigest v_md = MessageDigest.getInstance( "SHA-" + p_bits ); byte[] v_digest = v_md.digest( allBytesInBlob ); return RAW.newRAW(v_digest); } } / CREATE OR REPLACE FUNCTION sha2_string(p_string in VARCHAR2, p_bits in number) RETURN RAW AS LANGUAGE JAVA NAME 'sha2.get_digest_string( java.lang.String, int ) return oracle.sql.RAW'; / CREATE OR REPLACE FUNCTION sha2_blob(p_byte in BLOB, p_bits in number) RETURN RAW AS LANGUAGE JAVA NAME 'sha2.get_digest_blob( oracle.sql.BLOB, int ) return oracle.sql.RAW'; /
The above features work. Testing them, I get:
SELECT sha2_string('0123456789',256) FROM DUAL; SELECT sha2_blob(utl_raw.cast_to_raw('0123456789'),256) FROM DUAL;
SHA2_STRING ('0123456789', 256)
-------------------------------------------------- ------------------------------ 84D89877F0D4041EFB6BF91A16F0248F2FD573E6AF05C19F96BEDB9F882F7882
1 row selected.
SHA2_BLOB (UTL_RAW.CAST_TO_RAW ('0123456789'), 256)
-------------------------------------------------- ------------------------------ 84D89877F0D4041EFB6BF91A16F0248F2FD573E6AF05C19F96BEDB9F882F7882
1 row selected.
I use an insert or update on T_IMG before the trigger to calculate the hash of the SH256 image column.
CREATE OR REPLACE TRIGGER TEST.TR_IMG_UPSERT BEFORE INSERT OR UPDATE ON TEST.T_IMG FOR EACH ROW DECLARE imghash varchar2(128); vblob blob; BEGIN vblob := :new.IMG; IF(vblob IS NOT NULL)THEN
The trigger itself works; where it calculates and inserts the hash value on the data layout (manufactured string or blob), but not on the actual image blob data, when it produces the following error:
ORA-29532: Java call terminated with an uncaught Java exception: java.sql.SQLException: invalid empty operation
ORA-06512: on page "TEST.SHA2_BLOB", line 1
ORA-06512: on page "TEST.TR_IMG_UPSERT", line 13
ORA-04088: an error occurred while starting the trigger "TEST.TR_IMG_UPSERT"
The trigger seems to be reading data: new.IMG as an empty blob .
Why is this happening and how can I solve my problem of automatically calculating and inserting an image hash into the T_IMG table every time a row is inserted or updated in the T_IMG table?
Note. A hash cannot be provided by the client application by inserting / updating data rows.
ADIM