New test.
[mono.git] / mcs / class / System.Data.OracleClient / System.Data.OracleClient / OracleLob.cs
1 //
2 // OracleLob.cs 
3 //
4 // Part of the Mono class libraries at
5 // mcs/class/System.Data.OracleClient/System.Data.OracleClient
6 //
7 // Assembly: System.Data.OracleClient.dll
8 // Namespace: System.Data.OracleClient
9 //
10 // Author: Tim Coleman <tim@timcoleman.com>
11 //
12 // Copyright (C) Tim Coleman, 2003
13 //
14 // Licensed under the MIT/X11 License.
15 //
16
17 using System;
18 using System.Data.OracleClient.Oci;
19 using System.Data.SqlTypes;
20 using System.IO;
21 using System.Text;
22
23 namespace System.Data.OracleClient {
24         public sealed class OracleLob : Stream, ICloneable, IDisposable, INullable
25         {
26                 #region Fields
27
28                 public static readonly new OracleLob Null = new OracleLob ();
29
30                 internal OracleConnection connection;
31                 bool isBatched = false;
32                 bool isOpen = true;
33                 bool notNull = false;
34                 OciLobLocator locator;
35                 OracleType type;
36
37                 long length = -1;
38                 long position = 0;
39
40                 #endregion // Fields
41
42                 #region Constructors
43
44                 internal OracleLob ()
45                 {
46                 }
47
48                 internal OracleLob (OciLobLocator locator, OciDataType ociType)
49                 {
50                         notNull = true;
51                         this.locator = locator;
52
53                         switch (ociType) {
54                         case OciDataType.Blob:
55                                 type = OracleType.Blob;
56                                 break;
57                         case OciDataType.Clob:
58                                 type = OracleType.Clob;
59                                 break;
60                         }
61                 }
62
63                 #endregion // Constructors
64
65                 #region Properties
66
67                 public override bool CanRead {
68                         get { return (IsNull || isOpen); }
69                 }
70
71                 public override bool CanSeek {
72                         get { return (IsNull || isOpen); }
73                 }
74
75                 public override bool CanWrite {
76                         get { return isOpen; }
77                 }
78
79                 public int ChunkSize {
80                         [MonoTODO]
81                         get { 
82                                 AssertConnectionIsOpen ();
83                                 AssertObjectNotDisposed ();
84                                 return locator.GetChunkSize ();
85                         }
86                 }
87
88                 public OracleConnection Connection {
89                         get { return connection; }
90                 }
91
92                 public bool IsBatched {
93                         get { return isBatched; }
94                 }
95
96                 public bool IsNull {
97                         get { return !notNull; }
98                 }
99
100                 public bool IsTemporary {
101                         get { 
102                                 AssertConnectionIsOpen ();
103                                 AssertObjectNotDisposed ();
104                                 throw new NotImplementedException ();
105                         }
106                 }
107
108                 public override long Length {
109                         get { 
110                                 AssertConnectionIsOpen ();
111                                 AssertObjectNotDisposed ();
112                                 if (length >= 0)
113                                         return length;
114                                 return locator.GetLength (LobType == OracleType.Blob);
115                         }
116                 }
117
118                 public OracleType LobType {
119                         get { return type; }
120                 }
121
122                 internal OciLobLocator Locator {
123                         get { return locator; }
124                 }
125
126                 public override long Position {
127                         get { 
128                                 AssertConnectionIsOpen ();
129                                 AssertObjectNotDisposed ();
130                                 return position;
131                         }
132                         set {
133                                 AssertConnectionIsOpen ();
134                                 AssertObjectNotDisposed ();
135                                 position = value;
136                         }
137                 }
138
139                 public object Value {
140                         get { 
141                                 AssertObjectNotDisposed ();
142                                 if (IsNull)
143                                         return DBNull.Value;
144                                 
145                                 byte[] buffer = null;
146
147                                 int len = (int) Length;
148                                 if (len == 0) {
149                                         // LOB is not Null, but it is Empty
150                                         if (LobType == OracleType.Clob)
151                                                 return "";
152                                         else // OracleType.Blob
153                                                 return new byte[0];
154                                 }
155
156                                 if (LobType == OracleType.Clob) {
157                                         buffer = new byte [len];
158                                         Read (buffer, 0, len);
159                                         UnicodeEncoding encoding = new UnicodeEncoding ();
160                                         return encoding.GetString (buffer);
161                                 }
162                                 else {
163                                         // OracleType.Blob
164                                         buffer = new byte [len];
165                                         Read (buffer, 0, len);
166                                         return buffer;
167                                 }
168                         }
169                 }
170
171                 #endregion // Properties
172
173                 #region Methods
174
175                 [MonoTODO]
176                 public void Append (OracleLob source) 
177                 {
178                         if (source.IsNull)
179                                 throw new ArgumentNullException ();
180                         if (Connection.State == ConnectionState.Closed)
181                                 throw new InvalidOperationException ();
182                         throw new NotImplementedException ();
183                 }
184
185                 void AssertAmountIsEven (long amount, string argName)
186                 {
187                         if (amount % 2 == 1)
188                                 throw new ArgumentOutOfRangeException ("CLOB and NCLOB parameters require even number of bytes for this argument.");
189                 }
190
191                 void AssertAmountIsValid (long amount, string argName)
192                 {
193                         if (amount > UInt32.MaxValue)
194                                 throw new ArgumentOutOfRangeException ("Argument too big.");
195                         if (LobType == OracleType.Clob || LobType == OracleType.NClob)
196                                 AssertAmountIsEven (amount, argName);
197                 }
198
199                 void AssertConnectionIsOpen ()
200                 {
201                         if (connection.State == ConnectionState.Closed)
202                                 throw new InvalidOperationException ("Invalid operation. The connection is closed.");
203                 }
204
205                 void AssertObjectNotDisposed ()
206                 {
207                         if (!isOpen)
208                                 throw new ObjectDisposedException ("OracleLob");
209                 }
210
211                 void AssertTransactionExists ()
212                 {
213                         if (connection.Transaction == null)
214                                 throw new InvalidOperationException ("Modifying a LOB requires that the connection be transacted.");
215                 }
216
217                 public void BeginBatch ()
218                 {
219                         BeginBatch (OracleLobOpenMode.ReadOnly);
220                 }
221
222                 public void BeginBatch (OracleLobOpenMode mode)
223                 {
224                         AssertConnectionIsOpen ();
225                         AssertObjectNotDisposed ();
226
227                         locator.BeginBatch (mode);
228                         isBatched = true;
229                 }
230
231                 [MonoTODO]
232                 public object Clone ()
233                 {
234                         throw new NotImplementedException ();
235                 }
236
237                 [MonoTODO]
238                 public override void Close ()
239                 {
240                         locator.Dispose ();
241                         isOpen = false;
242                 }
243
244                 public long CopyTo (OracleLob destination)
245                 {
246                         return CopyTo (0, destination, 0, Length);
247                 }
248
249                 public long CopyTo (OracleLob destination, long destinationOffset)
250                 {
251                         return CopyTo (0, destination, destinationOffset, Length);
252                 }
253
254                 public long CopyTo (long sourceOffset, OracleLob destination, long destinationOffset, long amount)
255                 {
256                         if (destination.IsNull)
257                                 throw new ArgumentNullException ();
258
259                         AssertAmountIsValid (sourceOffset, "sourceOffset");
260                         AssertAmountIsValid (destinationOffset, "destinationOffset");
261                         AssertAmountIsValid (amount, "amount");
262                         AssertTransactionExists ();
263                         AssertConnectionIsOpen ();
264
265                         return (long) locator.Copy (destination.Locator, (uint) amount, (uint) destinationOffset + 1, (uint) sourceOffset + 1);
266                 }
267
268                 [MonoTODO]
269                 public void Dispose ()
270                 {
271                         throw new NotImplementedException ();
272                 }
273
274                 public void EndBatch ()
275                 {
276                         AssertConnectionIsOpen ();
277                         AssertObjectNotDisposed ();
278
279                         locator.EndBatch ();
280                         isBatched = false;
281                 }
282
283                 public long Erase ()
284                 {
285                         return Erase (0, Length);
286                 }
287
288                 public long Erase (long offset, long amount)
289                 {
290                         if (offset < 0 || amount < 0)
291                                 throw new ArgumentOutOfRangeException ("Must be a positive value.");
292                         if (offset + amount > Length)
293                                 throw new ArgumentOutOfRangeException ();
294
295                         AssertAmountIsValid (offset, "offset");
296                         AssertAmountIsValid (amount, "amount");
297
298                         return (long) locator.Erase ((uint) offset + 1, (uint) amount);
299                 }
300
301                 public override void Flush ()
302                 {
303                         // No-op
304                 }
305
306                 public override int Read (byte[] buffer, int offset, int count)
307                 {
308                         if (buffer == null)
309                                 throw new ArgumentNullException ();
310
311                         AssertAmountIsValid (offset, "offset");
312                         AssertAmountIsValid (count, "count");
313                         AssertConnectionIsOpen ();
314                         AssertObjectNotDisposed ();
315
316                         int bytesRead;
317                         byte[] output = new byte[count];
318
319                         bytesRead = locator.Read (output, (uint) Position + 1, (uint) count, LobType == OracleType.Blob);
320                         output.CopyTo (buffer, offset);
321                         position += bytesRead;
322                         return bytesRead;
323                 }
324
325                 [MonoTODO]
326                 public override long Seek (long offset, SeekOrigin origin)
327                 {
328                         long newPosition = position;
329
330                         switch (origin) {
331                         case SeekOrigin.Begin:
332                                 newPosition = offset;
333                                 break;
334                         case SeekOrigin.Current:
335                                 newPosition += offset;
336                                 break;
337                         case SeekOrigin.End:
338                                 newPosition = Length + offset;
339                                 break;
340                         }
341
342                         if (newPosition > Length)
343                                 throw new ArgumentOutOfRangeException ();
344
345                         position = newPosition;
346                         return position;
347                 }
348
349                 [MonoTODO]
350                 public override void SetLength (long value)
351                 {
352                         AssertAmountIsValid (value, "value");
353                         AssertTransactionExists ();
354                         AssertConnectionIsOpen ();
355                         AssertObjectNotDisposed ();
356
357                         locator.Trim ((uint) value);
358                         length = value;
359                 }
360
361                 public override void Write (byte[] buffer, int offset, int count)
362                 {
363                         if (buffer == null)
364                                 throw new ArgumentNullException ("Buffer is null.");
365                         if (offset < 0 || count < 0)
366                                 throw new ArgumentOutOfRangeException ("Must be a positive value.");
367                         if (offset + count > buffer.Length)
368                                 throw new ArgumentOutOfRangeException ("The offset and count values specified exceed the buffer provided.");
369                         AssertAmountIsValid (offset, "offset");
370                         AssertAmountIsValid (count, "count");
371                         AssertTransactionExists ();
372                         AssertConnectionIsOpen ();
373                         AssertObjectNotDisposed ();
374
375                         byte[] value = null;
376                         if (offset + count == buffer.Length && offset == 0)
377                                 value = buffer;
378                         else {
379                                 value = new byte[count];
380                                 Array.Copy (buffer, offset, value, 0, count);
381                         }
382
383                         position += locator.Write (value, (uint) Position + 1, (uint) value.Length, LobType);
384                 }
385
386                 #endregion // Methods
387         }
388 }