+2008-09-24 Daniel Morgan <monodanmorg@yahoo.com>
+
+ * Test/testblob.cs
+ * Test/TestOracleClient.cs: update tests for parameter type of blob
+
+ * System.Data.OracleClient/OracleLob.cs: position was never
+ being reset to the offset causing the reading of a Blob to
+ be out of range
+
+ * System.Data.OracleClient/OracleParameter.cs: fixes for
+ character and blob types
+
2008-09-16 Daniel Morgan <monodanmorg@yahoo.com>
* System.Data.OracleClient/OracleBFile.cs: do not
int bytesRead;
byte[] output = new byte [count];
+ position = offset;
bytesRead = locator.Read (output, (uint) Position + 1, (uint) count, LobType == OracleType.Blob);
output.CopyTo (buffer, offset);
position += bytesRead;
value = new byte[count];
Array.Copy (buffer, offset, value, 0, count);
}
-
position += locator.Write (value, (uint) Position + 1, (uint) value.Length, LobType);
}
if (direction == ParameterDirection.Input ||
direction == ParameterDirection.InputOutput) {
- svalue = v.ToString () + '\0';
+ svalue = v.ToString ();
+
+ if (direction == ParameterDirection.Input && size > 0 && svalue.Length > size)
+ svalue = svalue.Substring(0, size);
+
+ svalue = svalue.ToString () + '\0';
}
// set bind length to size of data
- bindSize = (size + 1) * 4;
+ //bindSize = (size + 1) * 4;
+ if (direction == ParameterDirection.Input)
+ bindSize = Encoding.UTF8.GetMaxByteCount (svalue.Length);
+ else
+ bindSize = Encoding.UTF8.GetMaxByteCount (size + 1);
// allocate memory based on bind length
- bytes = new byte[bindSize];
+ bytes = new byte [bindSize];
if (direction == ParameterDirection.Input ||
direction == ParameterDirection.InputOutput) {
break;
case OciDataType.Blob:
if (direction == ParameterDirection.Input) {
- bytes = (byte[]) v;
- bindType = OciDataType.LongRaw;
- bindSize = bytes.Length;
+ if (v is byte[]) {
+ bytes = (byte[]) v;
+ bindType = OciDataType.LongRaw;
+ bindSize = bytes.Length;
+ }
+ else if (v is OracleLob) {
+ OracleLob lob = (OracleLob) v;
+ if (lob.LobType == OracleType.Blob) {
+ lobLocator = lob.Locator;
+ bindOutValue = lobLocator.Handle;
+ bindValue = lobLocator.Handle;
+ lobLocator.ErrorHandle = connection.ErrorHandle;
+ lobLocator.Service = connection.ServiceContext;
+ useRef = true;
+ }
+ else
+ throw new NotImplementedException("For OracleType.Blob, data type OracleLob of LobType Clob/NClob is not implemented.");
+ }
+ else
+ throw new NotImplementedException ("For OracleType.Blob, data type not implemented: " + v.GetType().ToString()); // ?
}
else if (direction == ParameterDirection.InputOutput) {
// not the exact error that .net 2.0 throws, but this is better
}
else {
bindSize = -1;
- lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
+ if (value != null && value is OracleLob) {
+ OracleLob blob = (OracleLob) value;
+ if (blob.LobType == OracleType.Blob)
+ if (value != OracleLob.Null) {
+ lobLocator = blob.Locator;
+ byte[] bs = (byte[]) blob.Value;
+ bindSize = bs.Length;
+ }
+ }
if (lobLocator == null) {
- OciErrorInfo info = connection.ErrorHandle.HandleError ();
- throw new OracleException (info.ErrorCode, info.ErrorMessage);
+ lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
+ if (lobLocator == null) {
+ OciErrorInfo info = connection.ErrorHandle.HandleError ();
+ throw new OracleException (info.ErrorCode, info.ErrorMessage);
+ }
}
bindOutValue = lobLocator.Handle;
bindValue = lobLocator.Handle;
lobLocator.ErrorHandle = connection.ErrorHandle;
- lobLocator.Service = statement.Service;
+ lobLocator.Service = connection.ServiceContext;
useRef = true;
}
break;
OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
bindType = OciDataType.String;
- bindSize = svalue.Length;
+ bindSize = bytes.Length;
} // else oracleType
} // else - Input, Ouput...
break;
throw new ArgumentException (exception);
}
- if (!inferring)
+ if (!oracleTypeSet || !inferring )
oracleType = type;
bindOracleType = type;
}
break;
case OciDataType.Blob:
case OciDataType.Clob:
- OracleLob lob = new OracleLob (lobLocator, ociType);
- lob.connection = connection;
- value = lob;
+ if (value != null && value is OracleLob && value != OracleLob.Null) {
+ OracleLob lob2 = (OracleLob) value;
+ lob2.connection = connection;
+ }
+ else {
+ OracleLob lob = new OracleLob (lobLocator, ociType);
+ lob.connection = connection;
+ value = lob;
+ }
break;
case OciDataType.RSet: // REF CURSOR
OciStatementHandle cursorStatement = GetOutRefCursor (cmd);
p4.OracleType = OracleType.Clob;
Console.WriteLine("p4.OracleType [Clob]: " + p4.OracleType.ToString());
Console.WriteLine();
+
+ OracleParameter p5 = new OracleParameter ((string) null, new DateTime (2005, 3, 8));
+ Console.WriteLine("p5.OracleType [DateTime]: " + p5.OracleType.ToString());
+ }
+
+ public static void InsertBlobTest(OracleConnection con)
+ {
+ checkTNS();
+ SetupMyPackage(con);
+ InsertBlob(con);
+ }
+
+ public static void checkTNS()
+ {
+ //string tnsAdmin = System.Environment.GetEnvironmentVariable("TNS_ADMIN");
+ //if ( (tnsAdmin == null)|| (string.Empty.Equals(tnsAdmin)) )
+ //{
+ // System.Environment.SetEnvironmentVariable("TNS_ADMIN", "~/instantclient");
+ //}
+ }
+
+ public static decimal InsertBlob(OracleConnection con)
+ {
+ byte[] ByteArray = new byte[2000]; // test Blob data
+ byte j = 0;
+ for (int i = 0; i < ByteArray.Length; i++) {
+ ByteArray[i] = j;
+ if (j > 255)
+ j = 0;
+ j++;
+ }
+ Console.WriteLine("Test Blob Data beginning: " + GetHexString (ByteArray));
+
+ decimal retVal = -1;
+
+ string sproc = "MyPackage" + ".InsertBlob";
+
+ OracleCommand cmd = new OracleCommand();
+ cmd.CommandText = sproc;
+ cmd.CommandType = CommandType.StoredProcedure;
+ cmd.Connection = con;
+ //cmd.Connection.Open();
+ cmd.Transaction = cmd.Connection.BeginTransaction();
+
+ try {
+ OracleParameter p1 = new OracleParameter("i_Sig_File", OracleType.Blob);
+ p1.Direction = ParameterDirection.Input;
+
+ //EXCEPTION thrown here
+ //p1.Value = GetOracleLob(cmd.Transaction, ByteArray);
+ OracleLob lob2 = GetOracleLob(cmd.Transaction, ByteArray);
+ byte[] b2 = (byte[]) lob2.Value;
+ Console.WriteLine("Test Blob Data here: " + GetHexString (b2));
+ p1.Value = lob2.Value;
+ //p1.Value = ByteArray;
+
+ cmd.Parameters.Add(p1);
+
+ cmd.ExecuteNonQuery();
+
+ cmd.Transaction.Commit();
+
+ OracleCommand select = con.CreateCommand ();
+ //select.Transaction = transaction;
+ select.CommandText = "SELECT BLOB_COLUMN FROM BLOBTEST2";
+ Console.WriteLine (" SELECTING A BLOB (Binary) VALUE FROM BLOBTEST2");
+
+ OracleDataReader reader = select.ExecuteReader ();
+ if (!reader.Read ())
+ Console.WriteLine ("ERROR: RECORD NOT FOUND");
+
+ Console.WriteLine (" TESTING OracleLob OBJECT ...");
+ if (reader.IsDBNull(0))
+ Console.WriteLine("Lob IsNull");
+ else {
+ OracleLob lob = reader.GetOracleLob (0);
+ if (lob == OracleLob.Null)
+ Console.WriteLine("Lob is OracleLob.Null");
+ else {
+ byte[] blob = (byte[]) lob.Value;
+ string result = GetHexString(blob);
+ Console.WriteLine("Blob result: " + result);
+ if (ByteArrayCompare (ByteArray, blob))
+ Console.WriteLine("ByteArray and blob are the same: good");
+ else
+ Console.WriteLine("ByteArray and blob are not the same: bad");
+ }
+ }
+ }
+ catch(Exception ex) {
+ Console.WriteLine("I exploded:" + ex.ToString());
+ cmd.Transaction.Rollback();
+
+ }
+
+ return retVal;
+
+ }
+
+ private static OracleLob GetOracleLob(OracleTransaction transaction, byte[] blob)
+ {
+ string BLOB_CREATE = "DECLARE dpBlob BLOB; "
+ + "BEGIN "
+ + " DBMS_LOB.CREATETEMPORARY(dpBlob , False, 0); "
+ + " :tempBlob := dpBlob; "
+ + "END;";
+
+ OracleLob tempLob = OracleLob.Null;
+ if (blob != null)
+ {
+ // Create a new command using the same connection
+ OracleCommand command = transaction.Connection.CreateCommand();
+
+ // Assign the transaction to the command
+ command.Transaction = transaction;
+
+ // Create blob storage on the Oracle server
+ command.CommandText = BLOB_CREATE;
+
+ // Add a new output paramter to accept the blob storage reference
+ OracleParameter parm = new OracleParameter("tempBlob", OracleType.Blob);
+ parm.Direction = ParameterDirection.Output;
+ command.Parameters.Add(parm);
+// command.Parameters.Add(
+// new OracleParameter("tempBlob", OracleType.Blob)).Direction =
+// ParameterDirection.Output;
+
+ // Fire as your guns bear...
+ command.ExecuteNonQuery();
+
+ // Retrieve the blob stream from the OracleLob parameter
+ //tempLob = (OracleLob)command.Parameters[0].Value;
+ tempLob = (OracleLob) parm.Value;
+
+ // Prevent server side events from firing while we write to the stream
+ tempLob.BeginBatch(OracleLobOpenMode.ReadWrite);
+
+ // Write bytes to the stream
+ tempLob.Write(blob, 0, blob.Length);
+
+ // Resume firing server events
+ tempLob.EndBatch();
+ }
+
+ return tempLob;
+ }
+
+ static void SetupMyPackage(OracleConnection con) \r
+ {\r
+ Console.WriteLine("Setup Oracle package curspkg_join...");\r
+ \r
+ Console.WriteLine (" Drop table BLOBTEST2 ...");
+ try {
+ OracleCommand cmd2 = con.CreateCommand ();
+ //cmd2.Transaction = transaction;
+ cmd2.CommandText = "DROP TABLE BLOBTEST2";
+ cmd2.ExecuteNonQuery ();
+ }
+ catch (OracleException) {
+ // ignore if table already exists
+ }
+
+ Console.WriteLine (" CREATE TABLE ...");
+
+ OracleCommand create = con.CreateCommand ();
+ //create.Transaction = transaction;
+ create.CommandText = "CREATE TABLE BLOBTEST2 (BLOB_COLUMN BLOB)";
+ create.ExecuteNonQuery ();
+
+ create.CommandText = "commit";\r
+ create.ExecuteNonQuery();\r
+
+ Console.Error.WriteLine(" create or replace package MyPackage...");
+ OracleCommand cmd = con.CreateCommand();\r
+ cmd.CommandText = \r
+ "CREATE OR REPLACE PACKAGE MyPackage AS\n" +\r
+ " Procedure InsertBlob (i_Sig_File blob);\n" +\r
+ "END MyPackage;";\r
+ cmd.ExecuteNonQuery();
+\r
+ Console.Error.WriteLine(" create or replace package body MyPackage...");
+ cmd.CommandText = \r
+ "CREATE OR REPLACE PACKAGE BODY MyPackage AS\n" +\r
+ " Procedure InsertBlob (i_Sig_File blob)\n" +\r
+ " IS\n" +\r
+ " BEGIN\n" +
+ " INSERT INTO BLOBTEST2 (BLOB_COLUMN) VALUES(i_Sig_File); " +
+ " END InsertBlob; " +\r
+ "END MyPackage;";\r
+ cmd.ExecuteNonQuery();
+
+ cmd.CommandText = "commit";\r
+ cmd.ExecuteNonQuery();\r
+ }\r
+
+ static byte[] ByteArrayCombine (byte[] b1, byte[] b2)
+ {
+ if (b1 == null)
+ b1 = new byte[0];
+ if (b2 == null)
+ b2 = new byte[0];
+
+ byte[] bytes = new byte[b1.Length + b2.Length];
+ int i = 0;
+ for (int j = 0; j < b1.Length; j++) {
+ bytes[i] = b1[j];
+ i++;
+ }
+ for (int k = 0; k < b2.Length; k++) {
+ bytes[i] = b2[k];
+ i++;
+ }
+ return bytes;
+ }
+
+ static bool ByteArrayCompare(byte[] ba1, byte[] ba2)
+ {
+ if (ba1 == null && ba2 == null)
+ return true;
+
+ if (ba1 == null)
+ return false;
+
+ if (ba2 == null)
+ return false;
+
+ if (ba1.Length != ba2.Length)
+ return false;
+
+ // for (int i = 0; i < ba1.Length; i++)
+ // {
+ //Console.WriteLine("i: " + i.ToString() + " ba1: " + ba1[i].ToString() + " ba2: " + ba2[i].ToString());
+ //}
+
+ for (int i = 0; i < ba1.Length; i++)
+ {
+ if (ba1[i] != ba2[i])
+ return false;
+ }
+
+ return true;
}
[STAThread]
ShowConnectionProperties (con1);
+ InsertBlobTest (con1);
+
Console.WriteLine ("Mono Oracle Test BEGIN ...");
MonoTest (con1);
Console.WriteLine ("Mono Oracle Test END ...");
static string infilename = @"../../../tools/mono-win32-setup-dark.bmp";
static string outfilename = @"mono-win32-setup-dark2.bmp";
static string connectionString = "Data Source=testdb;User ID=scott;Password=tiger";
+ static byte[] bytes1 = null;
public static void Main (string[] args)
{
Console.WriteLine (" CHUNK SIZE: {0}", lob2.ChunkSize);
byte[] lobvalue = (byte[]) lob2.Value;
+
+ if (ByteArrayCompare(bytes1, lobvalue) == true)
+ Console.WriteLine("bytes1 and bytes2 are equal: good");
+ else
+ Console.WriteLine("bytes1 and bytes2 are not equal: bad");
FileStream fs = new FileStream(outfilename, FileMode.CreateNew);
BinaryWriter w = new BinaryWriter(fs);
cmd2.CommandText = "DROP TABLE BLOBTEST";
cmd2.ExecuteNonQuery ();
}
- catch (OracleException oe1) {
+ catch (OracleException) {
// ignore if table already exists
}
Console.WriteLine (" LENGTH: {0}", lob.Length);
Console.WriteLine (" CHUNK SIZE: {0}", lob.ChunkSize);
- try {
+ //try {
if (File.Exists(infilename) == false) {
Console.WriteLine("Filename does not exist: " + infilename);
return;
while(bytes.Length > 0) {
Console.WriteLine("byte count: " + bytes.Length.ToString());
lob.Write (bytes, 0, bytes.Length);
+ bytes1 = ByteArrayCombine (bytes1, bytes);
if (bytes.Length < bufferLen)
break;
bytes = r.ReadBytes (bufferLen);
r.Close();
fs.Close ();
- }
- catch (Exception e) {
- Console.WriteLine("The file could not be read:");
- Console.WriteLine(e.Message);
- }
+ //}
+ //catch (Exception e) {
+ // Console.WriteLine("The file could not be read:");
+ // Console.WriteLine(e.Message);
+ //}
lob.Close ();
insert = null;
select = null;
}
+
+ static byte[] ByteArrayCombine (byte[] b1, byte[] b2)
+ {
+ if (b1 == null)
+ b1 = new byte[0];
+ if (b2 == null)
+ b2 = new byte[0];
+
+ byte[] bytes = new byte[b1.Length + b2.Length];
+ int i = 0;
+ for (int j = 0; j < b1.Length; j++) {
+ bytes[i] = b1[j];
+ i++;
+ }
+ for (int k = 0; k < b2.Length; k++) {
+ bytes[i] = b2[k];
+ i++;
+ }
+ return bytes;
+ }
+
+ static bool ByteArrayCompare(byte[] ba1, byte[] ba2)
+ {
+ if (ba1 == null && ba2 == null)
+ return true;
+
+ if (ba1 == null)
+ return false;
+
+ if (ba2 == null)
+ return false;
+
+ if (ba1.Length != ba2.Length)
+ return false;
+
+ for (int i = 0; i < ba1.Length; i++)
+ {
+ Console.WriteLine("i: " + i.ToString() + " ba1: " + ba1[i].ToString() + " ba2: " + ba2[i].ToString());
+ }
+
+ for (int i = 0; i < ba1.Length; i++)
+ {
+ if (ba1[i] != ba2[i])
+ return false;
+ }
+
+ return true;
+ }
+
}