Applied patch from: David Pickens <dsp@rci.rutgers.edu>
[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, 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 = 1;
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 = new byte [Length];
146                                 Read (buffer, 1, (int) Length);
147
148                                 if (LobType == OracleType.Clob)
149                                         return (new UnicodeEncoding ()).GetString (buffer);
150                                 return buffer;
151                         }
152                 }
153
154                 #endregion // Properties
155
156                 #region Methods
157
158                 [MonoTODO]
159                 public void Append (OracleLob source) 
160                 {
161                         if (source.IsNull)
162                                 throw new ArgumentNullException ();
163                         if (Connection.State == ConnectionState.Closed)
164                                 throw new InvalidOperationException ();
165                         throw new NotImplementedException ();
166                 }
167
168                 void AssertAmountIsEven (long amount, string argName)
169                 {
170                         if (amount % 2 == 1)
171                                 throw new ArgumentOutOfRangeException ("CLOB and NCLOB parameters require even number of bytes for this argument.");
172                 }
173
174                 void AssertAmountIsValid (long amount, string argName)
175                 {
176                         if (amount > UInt32.MaxValue)
177                                 throw new ArgumentOutOfRangeException ("Argument too big.");
178                         if (LobType == OracleType.Clob || LobType == OracleType.NClob)
179                                 AssertAmountIsEven (amount, argName);
180                 }
181
182                 void AssertConnectionIsOpen ()
183                 {
184                         if (connection.State == ConnectionState.Closed)
185                                 throw new InvalidOperationException ("Invalid operation. The connection is closed.");
186                 }
187
188                 void AssertObjectNotDisposed ()
189                 {
190                         if (!isOpen)
191                                 throw new ObjectDisposedException ("OracleLob");
192                 }
193
194                 void AssertTransactionExists ()
195                 {
196                         if (connection.Transaction == null)
197                                 throw new InvalidOperationException ("Modifying a LOB requires that the connection be transacted.");
198                 }
199
200                 public void BeginBatch ()
201                 {
202                         BeginBatch (OracleLobOpenMode.ReadOnly);
203                 }
204
205                 public void BeginBatch (OracleLobOpenMode mode)
206                 {
207                         AssertConnectionIsOpen ();
208                         AssertObjectNotDisposed ();
209
210                         locator.BeginBatch (mode);
211                         isBatched = true;
212                 }
213
214                 [MonoTODO]
215                 public object Clone ()
216                 {
217                         throw new NotImplementedException ();
218                 }
219
220                 [MonoTODO]
221                 public override void Close ()
222                 {
223                         locator.Dispose ();
224                         isOpen = false;
225                 }
226
227                 public long CopyTo (OracleLob destination)
228                 {
229                         return CopyTo (0, destination, 0, Length);
230                 }
231
232                 public long CopyTo (OracleLob destination, long destinationOffset)
233                 {
234                         return CopyTo (0, destination, destinationOffset, Length);
235                 }
236
237                 public long CopyTo (long sourceOffset, OracleLob destination, long destinationOffset, long amount)
238                 {
239                         if (destination.IsNull)
240                                 throw new ArgumentNullException ();
241
242                         AssertAmountIsValid (sourceOffset, "sourceOffset");
243                         AssertAmountIsValid (destinationOffset, "destinationOffset");
244                         AssertAmountIsValid (amount, "amount");
245                         AssertTransactionExists ();
246                         AssertConnectionIsOpen ();
247
248                         return (long) locator.Copy (destination.Locator, (uint) amount, (uint) destinationOffset + 1, (uint) sourceOffset + 1);
249                 }
250
251                 [MonoTODO]
252                 public void Dispose ()
253                 {
254                         throw new NotImplementedException ();
255                 }
256
257                 public void EndBatch ()
258                 {
259                         AssertConnectionIsOpen ();
260                         AssertObjectNotDisposed ();
261
262                         locator.EndBatch ();
263                         isBatched = false;
264                 }
265
266                 public long Erase ()
267                 {
268                         return Erase (1, Length);
269                 }
270
271                 public long Erase (long offset, long amount)
272                 {
273                         if (offset < 0 || amount < 0)
274                                 throw new ArgumentOutOfRangeException ("Must be a positive value.");
275                         if (offset + amount > Length)
276                                 throw new ArgumentOutOfRangeException ();
277
278                         AssertAmountIsValid (offset, "offset");
279                         AssertAmountIsValid (amount, "amount");
280
281                         return (long) locator.Erase ((uint) offset + 1, (uint) amount);
282                 }
283
284                 public override void Flush ()
285                 {
286                         // No-op
287                 }
288
289                 public override int Read (byte[] buffer, int offset, int count)
290                 {
291                         if (buffer == null)
292                                 throw new ArgumentNullException ();
293
294                         AssertAmountIsValid (offset, "offset");
295                         AssertAmountIsValid (count, "count");
296                         AssertConnectionIsOpen ();
297                         AssertObjectNotDisposed ();
298
299                         int bytesRead;
300                         byte[] output = new byte[count];
301
302                         bytesRead = locator.Read (output, (uint) Position, (uint) count, LobType == OracleType.Blob);
303                         output.CopyTo (buffer, offset);
304                         position += bytesRead;
305                         return bytesRead;
306                 }
307
308                 [MonoTODO]
309                 public override long Seek (long offset, SeekOrigin origin)
310                 {
311                         long newPosition = position;
312
313                         switch (origin) {
314                         case SeekOrigin.Begin:
315                                 newPosition = offset;
316                                 break;
317                         case SeekOrigin.Current:
318                                 newPosition += offset;
319                                 break;
320                         case SeekOrigin.End:
321                                 newPosition = Length - offset;
322                                 break;
323                         }
324
325                         if (newPosition > Length)
326                                 throw new ArgumentOutOfRangeException ();
327
328                         position = newPosition;
329                         return position;
330                 }
331
332                 [MonoTODO]
333                 public override void SetLength (long value)
334                 {
335                         AssertAmountIsValid (value, "value");
336                         AssertTransactionExists ();
337                         AssertConnectionIsOpen ();
338                         AssertObjectNotDisposed ();
339
340                         locator.Trim ((uint) value);
341                         length = value;
342                 }
343
344                 public override void Write (byte[] buffer, int offset, int count)
345                 {
346                         if (buffer == null)
347                                 throw new ArgumentNullException ("Buffer is null.");
348                         if (offset < 0 || count < 0)
349                                 throw new ArgumentOutOfRangeException ("Must be a positive value.");
350                         if (offset + count > buffer.Length)
351                                 throw new ArgumentOutOfRangeException ("The offset and count values specified exceed the buffer provided.");
352                         AssertAmountIsValid (offset, "offset");
353                         AssertAmountIsValid (count, "count");
354                         AssertTransactionExists ();
355                         AssertConnectionIsOpen ();
356                         AssertObjectNotDisposed ();
357
358                         byte[] value = null;
359                         if (offset + count == buffer.Length && offset == 0)
360                                 value = buffer;
361                         else {
362                                 value = new byte[count];
363                                 Array.Copy (buffer, offset, value, 0, count);
364                         }
365
366                         position += locator.Write (value, (uint) Position, (uint) value.Length, LobType);
367                 }
368
369                 #endregion // Methods
370         }
371 }