// You can specify all values by your own or you can build default build and revision
// numbers with the '*' character (the default):
-[assembly: AssemblyVersion("0.4")]
+[assembly: AssemblyVersion("0.5")]
// The following attributes specify the key for the sign of your assembly. See the
// .NET Framework documentation for more information about signing.
// This is not required, if you don't want signing let these attributes like they're.
[assembly: AssemblyDelaySign(false)]
-[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyFile("Npgsql.snk")]
--- /dev/null
+//
+// System.Security.Cryptography HashAlgorithm Class implementation
+//
+// Authors:
+// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright 2001 by Matthew S. Ford.
+// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+//
+// Comment: Adapted to the Project from Mono CVS as Sebastien Pouliot suggested to enable
+// support of Npgsql MD5 authentication in platforms which don't have support for MD5 algorithm.
+//
+
+
+using System;
+using System.IO;
+
+
+namespace Npgsql
+{
+
+
+ // Comment: Removed the ICryptoTransform implementation as this interface may be not supported by
+ // all platforms.
+
+ internal abstract class HashAlgorithm : IDisposable{
+ protected byte[] HashValue; // Caches the hash after it is calculated. Accessed through the Hash property.
+ protected int HashSizeValue; // The size of the hash in bits.
+ protected int State; // nonzero when in use; zero when not in use
+ private bool disposed;
+
+ /// <summary>
+ /// Called from constructor of derived class.
+ /// </summary>
+ protected HashAlgorithm ()
+ {
+ disposed = false;
+ }
+
+ /// <summary>
+ /// Get whether or not the hash can transform multiple blocks at a time.
+ /// Note: MUST be overriden if descendant can transform multiple block
+ /// on a single call!
+ /// </summary>
+ public virtual bool CanTransformMultipleBlocks {
+ get { return true; }
+ }
+
+ public virtual bool CanReuseTransform {
+ get { return true; }
+ }
+
+ public void Clear()
+ {
+ // same as System.IDisposable.Dispose() which is documented
+ Dispose (true);
+ }
+
+ /// <summary>
+ /// Computes the entire hash of all the bytes in the byte array.
+ /// </summary>
+ public byte[] ComputeHash (byte[] input)
+ {
+ return ComputeHash (input, 0, input.Length);
+ }
+
+ public byte[] ComputeHash (byte[] buffer, int offset, int count)
+ {
+ if (disposed)
+ throw new ObjectDisposedException ("HashAlgorithm");
+
+ HashCore (buffer, offset, count);
+ HashValue = HashFinal ();
+ Initialize ();
+
+ return HashValue;
+ }
+
+ public byte[] ComputeHash (Stream inputStream)
+ {
+ // don't read stream unless object is ready to use
+ if (disposed)
+ throw new ObjectDisposedException ("HashAlgorithm");
+
+ int l = (int) (inputStream.Length - inputStream.Position);
+ byte[] buffer = new byte [l];
+ inputStream.Read (buffer, 0, l);
+
+ return ComputeHash (buffer, 0, l);
+ }
+
+ // Commented out because it uses the CryptoConfig which can't be available in all platforms
+
+ /// <summary>
+ /// Creates the default implementation of the default hash algorithm (SHA1).
+ /// </summary>
+ /*public static HashAlgorithm Create ()
+ {
+ return Create ("System.Security.Cryptography.HashAlgorithm");
+ }*/
+
+ /// <summary>
+ /// Creates a specific implementation of the general hash idea.
+ /// </summary>
+ /// <param name="hashName">Specifies which derived class to create.</param>
+ /*public static HashAlgorithm Create (string hashName)
+ {
+ return (HashAlgorithm) CryptoConfig.CreateFromName (hashName);
+ }*/
+
+
+
+ // Changed Exception type because it uses the CryptographicUnexpectedOperationException
+ // which can't be available in all platforms.
+ /// <summary>
+ /// Gets the previously computed hash.
+ /// </summary>
+ public virtual byte[] Hash {
+ get {
+ if (HashValue == null)
+ throw new Exception("HashValue is null");
+ return HashValue;
+ }
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, drives the hashing function.
+ /// </summary>
+ /// <param name="rgb"></param>
+ /// <param name="start"></param>
+ /// <param name="size"></param>
+ protected abstract void HashCore (byte[] rgb, int start, int size);
+
+ /// <summary>
+ /// When overridden in a derived class, this pads and hashes whatever data might be left in the buffers and then returns the hash created.
+ /// </summary>
+ protected abstract byte[] HashFinal ();
+
+ /// <summary>
+ /// Returns the size in bits of the hash.
+ /// </summary>
+ public virtual int HashSize {
+ get { return HashSizeValue; }
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, initializes the object to prepare for hashing.
+ /// </summary>
+ public abstract void Initialize ();
+
+ protected virtual void Dispose (bool disposing)
+ {
+ disposed = true;
+ }
+
+ /// <summary>
+ /// Must be overriden if not 1
+ /// </summary>
+ public virtual int InputBlockSize {
+ get { return 1; }
+ }
+
+ /// <summary>
+ /// Must be overriden if not 1
+ /// </summary>
+ public virtual int OutputBlockSize {
+ get { return 1; }
+ }
+
+ void IDisposable.Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this); // Finalization is now unnecessary
+ }
+
+ /// <summary>
+ /// Used for stream chaining. Computes hash as data passes through it.
+ /// </summary>
+ /// <param name="inputBuffer">The buffer from which to grab the data to be copied.</param>
+ /// <param name="inputOffset">The offset into the input buffer to start reading at.</param>
+ /// <param name="inputCount">The number of bytes to be copied.</param>
+ /// <param name="outputBuffer">The buffer to write the copied data to.</param>
+ /// <param name="outputOffset">At what point in the outputBuffer to write the data at.</param>
+ public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
+ HashCore (inputBuffer, inputOffset, inputCount);
+
+ return inputCount;
+ }
+
+ /// <summary>
+ /// Used for stream chaining. Computes hash as data passes through it. Finishes off the hash.
+ /// </summary>
+ /// <param name="inputBuffer">The buffer from which to grab the data to be copied.</param>
+ /// <param name="inputOffset">The offset into the input buffer to start reading at.</param>
+ /// <param name="inputCount">The number of bytes to be copied.</param>
+ public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
+ {
+ byte[] outputBuffer = new byte[inputCount];
+
+ Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, 0, inputCount);
+
+ HashCore (inputBuffer, inputOffset, inputCount);
+ HashValue = HashFinal ();
+ Initialize ();
+
+ return outputBuffer;
+ }
+ }
+
+}
--- /dev/null
+// created on 20/02/2003
+
+// Npgsql.MD5.cs
+//
+
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+
+
+//
+// System.Security.Cryptography MD5 Class implementation
+//
+// Authors:
+// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright 2001 by Matthew S. Ford.
+// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+//
+// Comment: Adapted to the Project from Mono CVS as Sebastien Pouliot suggested to enable
+// support of Npgsql MD5 authentication in platforms which don't have support for MD5 algorithm.
+//
+//
+//
+
+
+
+
+
+namespace Npgsql
+{
+
+
+ /// <summary>
+ /// Common base class for all derived MD5 implementations.
+ /// </summary>
+ internal abstract class MD5 : HashAlgorithm {
+ /// <summary>
+ /// Called from constructor of derived class.
+ /// </summary>
+ // Why is it protected when others abstract hash classes are public ?
+ protected MD5 ()
+ {
+ HashSizeValue = 128;
+ }
+
+ /// <summary>
+ /// Creates the default derived class.
+ /// </summary>
+ public static MD5 Create ()
+ {
+ //return Create ("System.Security.Cryptography.MD5");
+ return new MD5CryptoServiceProvider();
+ }
+
+
+ // Commented out because it uses the CryptoConfig which can't be available in all
+ // platforms.
+ /// <summary>
+ /// Creates a new derived implementation.
+ /// </summary>
+ /// <param name="hashName">Specifies which derived class to create</param>
+ /*public static new MD5 Create (string hashName)
+ {
+ return (MD5) CryptoConfig.CreateFromName (hashName);
+ }*/
+
+ }
+}
--- /dev/null
+//
+// System.Security.Cryptography MD5CryptoServiceProvider Class implementation
+//
+// Authors:
+// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
+// Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright 2001 by Matthew S. Ford.
+//
+// Comment: Adapted to the Project from Mono CVS as Sebastien Pouliot suggested to enable
+// support of Npgsql MD5 authentication in platforms which don't have support for MD5 algorithm.
+//
+
+
+using System;
+
+
+namespace Npgsql
+{
+ /// <summary>
+ /// C# implementation of the MD5 cryptographic hash function.
+ /// </summary>
+ #if USE_VERSION_1_0
+ internal class MD5CryptoServiceProvider : MD5 {
+ #else
+ internal sealed class MD5CryptoServiceProvider : MD5 {
+ #endif
+ private const int BLOCK_SIZE_BYTES = 64;
+ private const int HASH_SIZE_BYTES = 16;
+ private const int HASH_SIZE_BITS = 128;
+ [CLSCompliant(false)] private uint[] _H;
+ [CLSCompliant(false)] private uint count;
+ private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
+ private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
+
+ /// <summary>
+ /// Creates a new MD5CryptoServiceProvider.
+ /// </summary>
+ public MD5CryptoServiceProvider ()
+ {
+ _H = new uint[4];
+ HashSizeValue = HASH_SIZE_BITS;
+ _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
+
+ Initialize();
+ }
+
+ ~MD5CryptoServiceProvider ()
+ {
+ Dispose (false);
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // nothing to do (managed implementation)
+ }
+
+ /// <summary>
+ /// Drives the hashing function.
+ /// </summary>
+ /// <param name="rgb">Byte array containing the data to hash.</param>
+ /// <param name="start">Where in the input buffer to start.</param>
+ /// <param name="size">Size in bytes of the data in the buffer to hash.</param>
+ protected override void HashCore (byte[] rgb, int start, int size)
+ {
+ int i;
+ State = 1;
+
+ if (_ProcessingBufferCount != 0) {
+ if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
+ System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
+ _ProcessingBufferCount += size;
+ return;
+ }
+ else {
+ i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
+ System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
+ ProcessBlock (_ProcessingBuffer, 0);
+ _ProcessingBufferCount = 0;
+ start += i;
+ size -= i;
+ }
+ }
+
+ for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
+ ProcessBlock (rgb, start+i);
+ }
+
+ if (size%BLOCK_SIZE_BYTES != 0) {
+ System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
+ _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
+ }
+ }
+
+ /// <summary>
+ /// This finalizes the hash. Takes the data from the chaining variables and returns it.
+ /// </summary>
+ protected override byte[] HashFinal ()
+ {
+ byte[] hash = new byte[16];
+ int i, j;
+
+ ProcessFinalBlock(_ProcessingBuffer, 0, _ProcessingBufferCount);
+
+ for (i=0; i<4; i++) {
+ for (j=0; j<4; j++) {
+ hash[i*4+j] = (byte)(_H[i] >> j*8);
+ }
+ }
+
+ return hash;
+ }
+
+ /// <summary>
+ /// Resets the class after use. Called automatically after hashing is done.
+ /// </summary>
+ public override void Initialize ()
+ {
+ count = 0;
+ _ProcessingBufferCount = 0;
+
+ _H[0] = 0x67452301;
+ _H[1] = 0xefcdab89;
+ _H[2] = 0x98badcfe;
+ _H[3] = 0x10325476;
+ }
+
+ /// <summary>
+ /// This is the meat of the hash function. It is what processes each block one at a time.
+ /// </summary>
+ /// <param name="inputBuffer">Byte array to process data from.</param>
+ /// <param name="inputOffset">Where in the byte array to start processing.</param>
+ private void ProcessBlock (byte[] inputBuffer, int inputOffset)
+ {
+ uint[] buff = new uint[16];
+ uint a, b, c, d;
+ int i;
+
+ count += BLOCK_SIZE_BYTES;
+
+ for (i=0; i<16; i++) {
+ buff[i] = (uint)(inputBuffer[inputOffset+4*i])
+ | (((uint)(inputBuffer[inputOffset+4*i+1])) << 8)
+ | (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
+ | (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
+ }
+
+ a = _H[0];
+ b = _H[1];
+ c = _H[2];
+ d = _H[3];
+
+ // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
+ // Possibly roll up if this changes.
+
+
+ // ---- Round 1 --------
+
+ a += (((c ^ d) & b) ^ d) + (uint) Constants.C0 + buff [0];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + (uint) Constants.C1 + buff [1];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + (uint) Constants.C2 + buff [2];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + (uint) Constants.C3 + buff [3];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ a += (((c ^ d) & b) ^ d) + (uint) Constants.C4 + buff [4];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + (uint) Constants.C5 + buff [5];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + (uint) Constants.C6 + buff [6];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + (uint) Constants.C7 + buff [7];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ a += (((c ^ d) & b) ^ d) + (uint) Constants.C8 + buff [8];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + (uint) Constants.C9 + buff [9];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + (uint) Constants.C10 + buff [10];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + (uint) Constants.C11 + buff [11];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ a += (((c ^ d) & b) ^ d) + (uint) Constants.C12 + buff [12];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + (uint) Constants.C13 + buff [13];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + (uint) Constants.C14 + buff [14];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + (uint) Constants.C15 + buff [15];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+
+ // ---- Round 2 --------
+
+ a += (((b ^ c) & d) ^ c) + (uint) Constants.C16 + buff [1];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + (uint) Constants.C17 + buff [6];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + (uint) Constants.C18 + buff [11];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + (uint) Constants.C19 + buff [0];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ a += (((b ^ c) & d) ^ c) + (uint) Constants.C20 + buff [5];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + (uint) Constants.C21 + buff [10];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + (uint) Constants.C22 + buff [15];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + (uint) Constants.C23 + buff [4];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ a += (((b ^ c) & d) ^ c) + (uint) Constants.C24 + buff [9];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + (uint) Constants.C25 + buff [14];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + (uint) Constants.C26 + buff [3];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + (uint) Constants.C27 + buff [8];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ a += (((b ^ c) & d) ^ c) + (uint) Constants.C28 + buff [13];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + (uint) Constants.C29 + buff [2];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + (uint) Constants.C30 + buff [7];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + (uint) Constants.C31 + buff [12];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+
+ // ---- Round 3 --------
+
+ a += (b ^ c ^ d) + (uint) Constants.C32 + buff [5];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + (uint) Constants.C33 + buff [8];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + (uint) Constants.C34 + buff [11];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + (uint) Constants.C35 + buff [14];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ a += (b ^ c ^ d) + (uint) Constants.C36 + buff [1];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + (uint) Constants.C37 + buff [4];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + (uint) Constants.C38 + buff [7];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + (uint) Constants.C39 + buff [10];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ a += (b ^ c ^ d) + (uint) Constants.C40 + buff [13];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + (uint) Constants.C41 + buff [0];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + (uint) Constants.C42 + buff [3];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + (uint) Constants.C43 + buff [6];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ a += (b ^ c ^ d) + (uint) Constants.C44 + buff [9];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + (uint) Constants.C45 + buff [12];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + (uint) Constants.C46 + buff [15];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + (uint) Constants.C47 + buff [2];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+
+ // ---- Round 4 --------
+
+ a += (((~d) | b) ^ c) + (uint) Constants.C48 + buff [0];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += (((~c) | a) ^ b) + (uint) Constants.C49 + buff [7];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += (((~b) | d) ^ a) + (uint) Constants.C50 + buff [14];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += (((~a) | c) ^ d) + (uint) Constants.C51 + buff [5];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ a += (((~d) | b) ^ c) + (uint) Constants.C52 + buff [12];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += (((~c) | a) ^ b) + (uint) Constants.C53 + buff [3];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += (((~b) | d) ^ a) + (uint) Constants.C54 + buff [10];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += (((~a) | c) ^ d) + (uint) Constants.C55 + buff [1];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ a += (((~d) | b) ^ c) + (uint) Constants.C56 + buff [8];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += (((~c) | a) ^ b) + (uint) Constants.C57 + buff [15];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += (((~b) | d) ^ a) + (uint) Constants.C58 + buff [6];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += (((~a) | c) ^ d) + (uint) Constants.C59 + buff [13];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ a += (((~d) | b) ^ c) + (uint) Constants.C60 + buff [4];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += (((~c) | a) ^ b) + (uint) Constants.C61 + buff [11];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += (((~b) | d) ^ a) + (uint) Constants.C62 + buff [2];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += (((~a) | c) ^ d) + (uint) Constants.C63 + buff [9];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+
+ _H[0] += a;
+ _H[1] += b;
+ _H[2] += c;
+ _H[3] += d;
+ }
+
+ /// <summary>
+ /// Pads and then processes the final block.
+ /// </summary>
+ /// <param name="inputBuffer">Buffer to grab data from.</param>
+ /// <param name="inputOffset">Position in buffer in bytes to get data from.</param>
+ /// <param name="inputCount">How much data in bytes in the buffer to use.</param>
+ private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
+ {
+ byte[] fooBuffer;
+ int paddingSize;
+ int i;
+ uint size;
+
+ paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
+
+ if (paddingSize < 1)
+ paddingSize += BLOCK_SIZE_BYTES;
+
+
+ fooBuffer = new byte[inputCount+paddingSize+8];
+
+ for (i=0; i<inputCount; i++) {
+ fooBuffer[i] = inputBuffer[i+inputOffset];
+ }
+
+ fooBuffer[inputCount] = 0x80;
+ for (i=inputCount+1; i<inputCount+paddingSize; i++) {
+ fooBuffer[i] = 0x00;
+ }
+
+ size = (uint)(count+inputCount);
+ size *= 8;
+ fooBuffer[inputCount+paddingSize] = (byte)((size) >> 0);
+ fooBuffer[inputCount+paddingSize+1] = (byte)((size) >> 8);
+ fooBuffer[inputCount+paddingSize+2] = (byte)((size) >> 16);
+ fooBuffer[inputCount+paddingSize+3] = (byte)((size) >> 24);
+
+ fooBuffer[inputCount+paddingSize+4] = 0x00;
+ fooBuffer[inputCount+paddingSize+5] = 0x00;
+ fooBuffer[inputCount+paddingSize+6] = 0x00;
+ fooBuffer[inputCount+paddingSize+7] = 0x00;
+
+ ProcessBlock(fooBuffer, 0);
+
+ if (inputCount+paddingSize+8 == 128) {
+ ProcessBlock(fooBuffer, 64);
+ }
+ }
+
+ private enum Constants : uint {
+ C0 = 0xd76aa478, C1 = 0xe8c7b756, C2 = 0x242070db,
+ C3 = 0xc1bdceee, C4 = 0xf57c0faf, C5 = 0x4787c62a,
+ C6 = 0xa8304613, C7 = 0xfd469501, C8 = 0x698098d8,
+ C9 = 0x8b44f7af,C10 = 0xffff5bb1,C11 = 0x895cd7be,
+ C12 = 0x6b901122,C13 = 0xfd987193,C14 = 0xa679438e,
+ C15 = 0x49b40821,C16 = 0xf61e2562,C17 = 0xc040b340,
+ C18 = 0x265e5a51,C19 = 0xe9b6c7aa,C20 = 0xd62f105d,
+ C21 = 0x02441453,C22 = 0xd8a1e681,C23 = 0xe7d3fbc8,
+ C24 = 0x21e1cde6,C25 = 0xc33707d6,C26 = 0xf4d50d87,
+ C27 = 0x455a14ed,C28 = 0xa9e3e905,C29 = 0xfcefa3f8,
+ C30 = 0x676f02d9,C31 = 0x8d2a4c8a,C32 = 0xfffa3942,
+ C33 = 0x8771f681,C34 = 0x6d9d6122,C35 = 0xfde5380c,
+ C36 = 0xa4beea44,C37 = 0x4bdecfa9,C38 = 0xf6bb4b60,
+ C39 = 0xbebfbc70,C40 = 0x289b7ec6,C41 = 0xeaa127fa,
+ C42 = 0xd4ef3085,C43 = 0x04881d05,C44 = 0xd9d4d039,
+ C45 = 0xe6db99e5,C46 = 0x1fa27cf8,C47 = 0xc4ac5665,
+ C48 = 0xf4292244,C49 = 0x432aff97,C50 = 0xab9423a7,
+ C51 = 0xfc93a039,C52 = 0x655b59c3,C53 = 0x8f0ccc92,
+ C54 = 0xffeff47d,C55 = 0x85845dd1,C56 = 0x6fa87e4f,
+ C57 = 0xfe2ce6e0,C58 = 0xa3014314,C59 = 0x4e0811a1,
+ C60 = 0xf7537e82,C61 = 0xbd3af235,C62 = 0x2ad7d2bb,
+ C63 = 0xeb86d391
+ }
+
+ }
+}
+
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
using System.IO;
using System.Text;
using System.Net;
+using NpgsqlTypes;
+
namespace Npgsql
{
private Byte[] null_map_array;
private Int16 num_fields;
private readonly Int16 READ_BUFFER_SIZE = 300; //[FIXME] Is this enough??
+ private NpgsqlRowDescription row_desc;
+ private Hashtable oid_to_name_mapping;
- public NpgsqlAsciiRow(Int16 numFields)
+ public NpgsqlAsciiRow(NpgsqlRowDescription rowDesc, Hashtable oidToNameMapping)
{
NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlAsciiRow()", LogLevel.Debug);
data = new ArrayList();
- null_map_array = new Byte[(numFields + 7)/8];
- num_fields = numFields;
+ row_desc = rowDesc;
+ null_map_array = new Byte[(row_desc.NumFields + 7)/8];
+ oid_to_name_mapping = oidToNameMapping;
+ //num_fields = numFields;
+
+
}
Array.Clear(null_map_array, 0, null_map_array.Length);
// Read the null fields bitmap.
- inputStream.Read(null_map_array, 0, null_map_array.Length );
+ PGUtil.CheckedStreamRead(inputStream, null_map_array, 0, null_map_array.Length );
// Get the data.
- for (Int16 field_count = 0; field_count < num_fields; field_count++)
+ for (Int16 field_count = 0; field_count < row_desc.NumFields; field_count++)
{
// Check if this field isn't null
// Add them to the AsciiRow data.
- data.Add(result.ToString());
+ data.Add(NpgsqlTypesHelper.ConvertBackendStringToSystemType(oid_to_name_mapping, result.ToString(), row_desc[field_count].type_oid, row_desc[field_count].type_modifier));
}
// Should this be public or internal?
// Check valid index range.
- if ((index < 0) || (index >= num_fields))
+ if ((index < 0) || (index >= row_desc.NumFields))
throw new ArgumentOutOfRangeException("index");
// Check if the value (index) of the field is null
get
{
- if ((index < 0) || (index >= num_fields))
+ if ((index < 0) || (index >= row_desc.NumFields))
throw new ArgumentOutOfRangeException("this[] index value");
// [FIXME] Should return null or something else
// more meaningful?
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
// This library is free software; you can redistribute it and/or
--- /dev/null
+// created on 4/3/2003 at 19:45
+
+// Npgsql.NpgsqlBinaryRow.cs
+//
+// Author:
+// Francisco Jr. (fxjrlists@yahoo.com.br)
+//
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+using System.Net;
+using NpgsqlTypes;
+
+
+namespace Npgsql
+{
+
+ /// <summary>
+ /// This class represents the AsciiRow message sent from PostgreSQL
+ /// server.
+ /// </summary>
+ ///
+ internal sealed class NpgsqlBinaryRow
+ {
+ // Logging related values
+ private static readonly String CLASSNAME = "NpgsqlBinaryRow";
+
+ private ArrayList data;
+ private Byte[] null_map_array;
+ private Int16 num_fields;
+ private readonly Int16 READ_BUFFER_SIZE = 300; //[FIXME] Is this enough??
+ private NpgsqlRowDescription row_desc;
+
+ public NpgsqlBinaryRow(NpgsqlRowDescription rowDesc)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlBinaryRow()", LogLevel.Debug);
+
+ data = new ArrayList();
+ row_desc = rowDesc;
+ null_map_array = new Byte[(row_desc.NumFields + 7)/8];
+ //num_fields = numFields;
+
+
+ }
+
+
+ public void ReadFromStream(Stream inputStream, Encoding encoding)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ReadFromStream()", LogLevel.Debug);
+
+ //Byte[] input_buffer = new Byte[READ_BUFFER_SIZE];
+ Byte[] input_buffer = null;
+
+ Array.Clear(null_map_array, 0, null_map_array.Length);
+
+ // Read the null fields bitmap.
+ inputStream.Read(null_map_array, 0, null_map_array.Length );
+
+ // Get the data.
+ for (Int16 field_count = 0; field_count < row_desc.NumFields; field_count++)
+ {
+
+ // Check if this field isn't null
+ if (IsNull(field_count))
+ {
+ // Field is null just keep next field.
+
+ //[FIXME] See this[] method.
+ data.Add(null);
+ continue;
+ }
+
+ // Read the first data of the first row.
+
+ PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, 4);
+
+ Int32 field_value_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
+
+ Int32 bytes_left = field_value_size; //Size of data is the value read.
+
+ input_buffer = new Byte[bytes_left];
+
+
+ //StringBuilder result = new StringBuilder();
+
+ /*while (bytes_left > READ_BUFFER_SIZE)
+ {
+ // Now, read just the field value.
+ PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, READ_BUFFER_SIZE);
+
+ // Read the bytes as string.
+ result.Append(new String(encoding.GetChars(input_buffer, 0, READ_BUFFER_SIZE)));
+
+ bytes_left -= READ_BUFFER_SIZE;
+ }
+ */
+ // Now, read just the field value.
+ PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, bytes_left);
+
+ // Read the bytes as string.
+ //result.Append(new String(encoding.GetChars(input_buffer, 0, bytes_left)));
+
+
+ // Add them to the BinaryRow data.
+ //data.Add(NpgsqlTypesHelper.ConvertStringToNpgsqlType(result.ToString(), row_desc[field_count].type_oid));
+ data.Add(input_buffer);
+
+ }
+
+ }
+
+
+ public Boolean IsNull(Int32 index)
+ {
+ // [FIXME] Check more optimized way of doing this.
+ // Should this be public or internal?
+
+ // Check valid index range.
+ if ((index < 0) || (index >= row_desc.NumFields))
+ throw new ArgumentOutOfRangeException("index");
+
+ // Check if the value (index) of the field is null
+
+ // Get the byte that holds the bit index position.
+ Byte test_byte = null_map_array[index/8];
+
+ // Now, check if index bit is set.
+ // To this, get its position in the byte, shift to
+ // MSB and test it with the byte 10000000.
+ return (((test_byte << (index%8)) & 0x80) == 0);
+ }
+
+
+ public Object this[Int32 index]
+ {
+ get
+ {
+
+ if ((index < 0) || (index >= row_desc.NumFields))
+ throw new ArgumentOutOfRangeException("this[] index value");
+ // [FIXME] Should return null or something else
+ // more meaningful?
+
+ //[FIXME] This code assumes that the data arraylist has the null and non null values
+ // in order, but just the non-null values are added.
+ // It is necessary to map the index value with the elements in the array list.
+ // For now, the workaround is to insert the null values in the array list.
+ // But this is a hack. :)
+
+ //return (IsNull(index) ? null : data[index]);
+ return data[index];
+
+
+
+ }
+ }
+ }
+
+}
// Dave Joyner <d4ljoyn@yahoo.com>
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// created on 21/5/2002 at 20:03\r
-\r
-// Npgsql.NpgsqlCommand.cs\r
-// \r
-// Author:\r
-// Francisco Jr. (fxjrlists@yahoo.com.br)\r
-//\r
-// Copyright (C) 2002 The Npgsql Development Team\r
-//\r
-\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
-\r
-using System;\r
-using System.Data;\r
-using System.Net;\r
-using System.Net.Sockets;\r
-using System.IO;\r
-using System.Text;\r
-using System.Collections;\r
-\r
-namespace Npgsql\r
-{\r
- public sealed class NpgsqlCommand : IDbCommand\r
- {\r
- \r
- private NpgsqlConnection connection;\r
- private String text;\r
- private Int32 timeout;\r
- private CommandType type;\r
- private NpgsqlParameterCollection parameters;\r
- private String planName;\r
- private static Int32 planIndex = 0;\r
- // Logging related values\r
- private static readonly String CLASSNAME = "NpgsqlCommand";\r
- \r
- // Constructors\r
- \r
- public NpgsqlCommand() : this(null, null){}\r
- \r
- public NpgsqlCommand(String cmdText) : this(cmdText, null){}\r
- \r
- \r
- public NpgsqlCommand(String cmdText, NpgsqlConnection connection)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlCommand()", LogLevel.Debug);\r
- \r
- planName = String.Empty;\r
- text = cmdText;\r
- this.connection = connection;\r
- parameters = new NpgsqlParameterCollection();\r
- timeout = 20;\r
- type = CommandType.Text; \r
- }\r
- \r
- // Public properties.\r
- \r
- public String CommandText\r
- {\r
- get\r
- {\r
- return text;\r
- }\r
- \r
- set\r
- {\r
- // [TODO] Validate commandtext.\r
- text = value;\r
- NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".CommandText = " + value, LogLevel.Normal);\r
- planName = String.Empty;\r
- }\r
- }\r
- \r
- public Int32 CommandTimeout\r
- {\r
- get\r
- {\r
- return timeout;\r
- }\r
- \r
- set\r
- {\r
- if (value < 0)\r
- throw new ArgumentException("CommandTimeout can't be less than zero");\r
- \r
- timeout = value;\r
- NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".CommandTimeout = " + value, LogLevel.Normal);\r
- }\r
- }\r
- \r
- public CommandType CommandType\r
- {\r
- get\r
- {\r
- return type;\r
- }\r
- \r
- set\r
- {\r
- type = value;\r
- NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".CommandType = " + value, LogLevel.Normal);\r
- }\r
- \r
- }\r
- \r
- IDbConnection IDbCommand.Connection\r
- {\r
- get\r
- {\r
- return Connection;\r
- }\r
- \r
- set\r
- {\r
- connection = (NpgsqlConnection) value;\r
- NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".IDbCommand.Connection", LogLevel.Debug);\r
- }\r
- }\r
- \r
- public NpgsqlConnection Connection\r
- {\r
- get\r
- {\r
- NpgsqlEventLog.LogMsg(CLASSNAME + ".get_Connection", LogLevel.Debug);\r
- return connection;\r
- }\r
- \r
- set\r
- {\r
- connection = value;\r
- NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".Connection", LogLevel.Debug);\r
- }\r
- }\r
- \r
- IDataParameterCollection IDbCommand.Parameters\r
- {\r
- get\r
- {\r
- return Parameters;\r
- }\r
- }\r
- \r
- public NpgsqlParameterCollection Parameters\r
- {\r
- get\r
- {\r
- NpgsqlEventLog.LogMsg(CLASSNAME + ".get_Parameters", LogLevel.Debug);\r
- return parameters;\r
- }\r
- }\r
- \r
- public IDbTransaction Transaction\r
- {\r
- get\r
- {\r
- throw new NotImplementedException();\r
- }\r
- \r
- set\r
- {\r
- throw new NotImplementedException(); \r
- }\r
- }\r
- \r
- public UpdateRowSource UpdatedRowSource\r
- {\r
- get\r
- {\r
- \r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_UpdatedRowSource()", LogLevel.Debug);\r
- // [FIXME] Strange, the line below doesn't appears in the stack trace.\r
- \r
- //throw new NotImplementedException();\r
- return UpdateRowSource.Both;\r
- }\r
- \r
- set\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
- \r
- public void Cancel()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Cancel()", LogLevel.Debug);\r
- \r
- // [TODO] Finish method implementation.\r
- throw new NotImplementedException();\r
- }\r
- \r
- \r
- IDbDataParameter IDbCommand.CreateParameter()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".IDbCommand.CreateParameter()", LogLevel.Debug);\r
- \r
- return (NpgsqlParameter) CreateParameter();\r
- }\r
- \r
- public NpgsqlParameter CreateParameter()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CreateParameter()", LogLevel.Debug);\r
- \r
- return new NpgsqlParameter();\r
- }\r
- \r
- public Int32 ExecuteNonQuery()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteNonQuery()", LogLevel.Debug);\r
- \r
- // Check the connection state.\r
- CheckConnectionState();\r
- \r
- if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))\r
- connection.Query(this); \r
- else\r
- throw new NotImplementedException("Only Text and StoredProcedure types supported!");\r
- \r
- \r
- \r
- // Check if there were any errors.\r
- // [FIXME] Just check the first error.\r
- if (connection.Mediator.Errors.Count > 0)\r
- throw new NpgsqlException(connection.Mediator.Errors[0].ToString());\r
- \r
- // The only expected result is the CompletedResponse result.\r
- \r
- String[] ret_string_tokens = ((String)connection.Mediator.GetCompletedResponses()[0]).Split(null); // whitespace separator.\r
- \r
- // Check if the command was insert, delete or update.\r
- // Only theses commands return rows affected.\r
- // [FIXME] Is there a better way to check this??\r
- if ((String.Compare(ret_string_tokens[0], "INSERT", true) == 0) ||\r
- (String.Compare(ret_string_tokens[0], "UPDATE", true) == 0) ||\r
- (String.Compare(ret_string_tokens[0], "DELETE", true) == 0))\r
- \r
- // The number of rows affected is in the third token for insert queries\r
- // and in the second token for update and delete queries.\r
- // In other words, it is the last token in the 0-based array.\r
- \r
- return Int32.Parse(ret_string_tokens[ret_string_tokens.Length - 1]);\r
- else\r
- return -1;\r
- \r
- }\r
- \r
- IDataReader IDbCommand.ExecuteReader()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader() implicit impl", LogLevel.Debug);\r
- \r
- return (NpgsqlDataReader) ExecuteReader();\r
- }\r
- \r
- IDataReader IDbCommand.ExecuteReader(CommandBehavior cb)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader() implicit impl(cb)", LogLevel.Debug);\r
- \r
- return (NpgsqlDataReader) ExecuteReader(cb);\r
- \r
- }\r
- \r
- public NpgsqlDataReader ExecuteReader()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader()", LogLevel.Debug);\r
- \r
- \r
- return ExecuteReader(CommandBehavior.Default);\r
- \r
- }\r
- \r
- public NpgsqlDataReader ExecuteReader(CommandBehavior cb)\r
- {\r
- // [FIXME] No command behavior handling.\r
- \r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader(CommandBehavior)", LogLevel.Debug);\r
- \r
- // Check the connection state.\r
- CheckConnectionState();\r
- \r
- if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))\r
- connection.Query(this); \r
- else\r
- throw new NotImplementedException("Only Text and StoredProcedure types supported!");\r
- \r
- \r
- // Check if there were any errors.\r
- // [FIXME] Just check the first error.\r
- if (connection.Mediator.Errors.Count > 0)\r
- throw new NpgsqlException(connection.Mediator.Errors[0].ToString());\r
- \r
- \r
- // Get the resultsets and create a Datareader with them.\r
- return new NpgsqlDataReader(connection.Mediator.GetResultSets(), connection.Mediator.GetCompletedResponses(), connection);\r
- }\r
- \r
- public Object ExecuteScalar()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteScalar()", LogLevel.Debug);\r
- \r
- // Check the connection state.\r
- CheckConnectionState();\r
- \r
- if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))\r
- connection.Query(this); \r
- else\r
- throw new NotImplementedException("Only Text and StoredProcedure types supported!");\r
- \r
- \r
- // Check if there were any errors.\r
- // [FIXME] Just check the first error.\r
- if (connection.Mediator.Errors.Count > 0)\r
- throw new NpgsqlException(connection.Mediator.Errors[0].ToString());\r
- \r
- \r
- //ArrayList results = connection.Mediator.Data;\r
- \r
- Object result = null; // Result of the ExecuteScalar().\r
- \r
- \r
- // Now get the results.\r
- // Only the first column of the first row must be returned.\r
- \r
- // Get ResultSets.\r
- ArrayList resultSets = connection.Mediator.GetResultSets();\r
- \r
- \r
- // First data is the RowDescription object.\r
- //NpgsqlRowDescription rd = (NpgsqlRowDescription)results[0];\r
- \r
- NpgsqlResultSet firstResultSet = (NpgsqlResultSet)resultSets[0];\r
- \r
- NpgsqlRowDescription rd = firstResultSet.RowDescription;\r
- \r
- NpgsqlAsciiRow ascii_row = (NpgsqlAsciiRow)firstResultSet[0];\r
- \r
- // Now convert the string to the field type.\r
- \r
- // [FIXME] Hardcoded values for int types and string.\r
- // Change to NpgsqlDbType.\r
- // For while only int4 and string are strong typed.\r
- // Any other type will be returned as string.\r
- \r
- switch (rd[0].type_oid)\r
- {\r
- case 20: // int8, integer.\r
- result = Convert.ToInt64(ascii_row[0]);\r
- break;\r
- case 23: // int4, integer.\r
- result = Convert.ToInt32(ascii_row[0]);\r
- break;\r
- case 25: // text\r
- // Get only the first column.\r
- result = ascii_row[0];\r
- break;\r
- default:\r
- NpgsqlEventLog.LogMsg("Unrecognized datatype returned by ExecuteScalar():" + \r
- rd[0].type_oid + " Returning String...", LogLevel.Debug);\r
- result = ascii_row[0];\r
- break;\r
- }\r
- \r
- return result;\r
- \r
- }\r
- \r
- \r
- \r
- public void Prepare()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Prepare()", LogLevel.Debug);\r
- \r
- // Check the connection state.\r
- CheckConnectionState();\r
- \r
- // [TODO] Finish method implementation.\r
- //throw new NotImplementedException();\r
- \r
- //NpgsqlCommand command = new NpgsqlCommand("prepare plan1 as " + GetCommandText(), connection );\r
- NpgsqlCommand command = new NpgsqlCommand(GetPrepareCommandText(), connection ); \r
- command.ExecuteNonQuery();\r
- \r
- \r
- \r
- }\r
- \r
- public void Dispose()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Dispose()", LogLevel.Debug);\r
- \r
- }\r
- \r
- ///<summary>\r
- /// This method checks the connection state to see if the connection\r
- /// is set or it is open. If one of this conditions is not met, throws\r
- /// an InvalidOperationException\r
- ///</summary>\r
- \r
- private void CheckConnectionState()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CheckConnectionState()", LogLevel.Debug);\r
- \r
- // Check the connection state.\r
- if (connection == null)\r
- throw new InvalidOperationException("The Connection is not set");\r
- if (connection.State != ConnectionState.Open)\r
- throw new InvalidOperationException("The Connection is not open");\r
- \r
- }\r
- \r
- ///<summary>\r
- /// This method substitutes the parameters, if exist, in the command\r
- /// to their actual values.\r
- /// The parameter name format is <b>:ParameterName</b>.\r
- /// </summary>\r
- /// \r
- \r
- internal String GetCommandText()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetCommandText()", LogLevel.Debug);\r
- \r
- if (planName == String.Empty)\r
- return GetClearCommandText();\r
- else\r
- return GetPreparedCommandText();\r
- \r
- \r
- }\r
- \r
- \r
- private String GetClearCommandText()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetClearCommandText()", LogLevel.Debug);\r
- \r
- \r
- String result = text;\r
- \r
- if (type == CommandType.StoredProcedure)\r
- result = "select " + result;\r
- \r
- if (parameters.Count == 0)\r
- return result;\r
- \r
- \r
- CheckParameters();\r
- \r
- String parameterName;\r
- \r
- for (Int32 i = 0; i < parameters.Count; i++)\r
- {\r
- parameterName = parameters[i].ParameterName;\r
- result = result.Replace(":" + parameterName, parameters[i].Value.ToString());\r
- }\r
- \r
- return result;\r
- \r
- }\r
- \r
- \r
- \r
- private String GetPreparedCommandText()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetPreparedCommandText()", LogLevel.Debug);\r
- \r
- if (parameters.Count == 0)\r
- return "execute " + planName;\r
- \r
- CheckParameters();\r
- \r
- StringBuilder result = new StringBuilder("execute " + planName + '(');\r
- \r
- \r
- for (Int32 i = 0; i < parameters.Count; i++)\r
- {\r
- result.Append(parameters[i].Value.ToString() + ',');\r
- //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());\r
- }\r
- \r
- result = result.Remove(result.Length - 1, 1);\r
- result.Append(')');\r
- \r
- return result.ToString();\r
- \r
- }\r
- \r
- \r
- private String GetPrepareCommandText()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetPrepareCommandText()", LogLevel.Debug);\r
- \r
- \r
- planName = "NpgsqlPlan" + System.Threading.Interlocked.Increment(ref planIndex);\r
- \r
- StringBuilder command = new StringBuilder("prepare " + planName);\r
- \r
- String textCommand = text;\r
- \r
- if (type == CommandType.StoredProcedure)\r
- textCommand = "select " + textCommand;\r
- \r
- \r
- \r
- if (parameters.Count > 0)\r
- {\r
- CheckParameters();\r
- \r
- command.Append('(');\r
- Int32 i;\r
- for (i = 0; i < parameters.Count; i++)\r
- {\r
- //[TODO] Add support for all types. \r
- \r
- switch (parameters[i].DbType)\r
- {\r
- case DbType.Int32:\r
- command.Append("int4");\r
- break;\r
- \r
- case DbType.Int64:\r
- command.Append("int8");\r
- break;\r
- \r
- default:\r
- throw new InvalidOperationException("Only DbType.Int32, DbType.Int64 datatypes supported");\r
- \r
- }\r
- \r
- command.Append(',');\r
- }\r
- \r
- command = command.Remove(command.Length - 1, 1);\r
- command.Append(')');\r
- \r
- \r
- String parameterName;\r
- \r
- for (i = 0; i < parameters.Count; i++)\r
- {\r
- //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());\r
- parameterName = parameters[i].ParameterName;\r
- textCommand = textCommand.Replace(':' + parameterName, "$" + (i+1));\r
- }\r
- \r
- }\r
- \r
- \r
- command.Append(" as ");\r
- command.Append(textCommand);\r
- \r
- \r
- return command.ToString();\r
- \r
- }\r
- \r
- private void CheckParameters()\r
- {\r
- String parameterName;\r
- \r
- for (Int32 i = 0; i < parameters.Count; i++)\r
- {\r
- parameterName = parameters[i].ParameterName;\r
- if (text.IndexOf(':' + parameterName) <= 0)\r
- throw new NpgsqlException("Parameter :" + parameterName + " wasn't found in the query.");\r
- }\r
- \r
- \r
- \r
- }\r
- }\r
- \r
-}\r
+// created on 21/5/2002 at 20:03
+
+// Npgsql.NpgsqlCommand.cs
+//
+// Author:
+// Francisco Jr. (fxjrlists@yahoo.com.br)
+//
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+using System;
+using System.Data;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Text;
+using System.Collections;
+using NpgsqlTypes;
+
+namespace Npgsql
+{
+ public sealed class NpgsqlCommand : IDbCommand
+ {
+
+ private NpgsqlConnection connection;
+ private String text;
+ private Int32 timeout;
+ private CommandType type;
+ private NpgsqlParameterCollection parameters;
+ private String planName;
+ private static Int32 planIndex = 0;
+ // Logging related values
+ private static readonly String CLASSNAME = "NpgsqlCommand";
+
+ // Constructors
+
+ public NpgsqlCommand() : this(null, null){}
+
+ public NpgsqlCommand(String cmdText) : this(cmdText, null){}
+
+
+ public NpgsqlCommand(String cmdText, NpgsqlConnection connection)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlCommand()", LogLevel.Debug);
+
+ planName = String.Empty;
+ text = cmdText;
+ this.connection = connection;
+ parameters = new NpgsqlParameterCollection();
+ timeout = 20;
+ type = CommandType.Text;
+ }
+
+ // Public properties.
+
+ public String CommandText
+ {
+ get
+ {
+ return text;
+ }
+
+ set
+ {
+ // [TODO] Validate commandtext.
+ text = value;
+ NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".CommandText = " + value, LogLevel.Normal);
+ planName = String.Empty;
+ }
+ }
+
+ public Int32 CommandTimeout
+ {
+ get
+ {
+ return timeout;
+ }
+
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("CommandTimeout can't be less than zero");
+
+ timeout = value;
+ NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".CommandTimeout = " + value, LogLevel.Normal);
+ }
+ }
+
+ public CommandType CommandType
+ {
+ get
+ {
+ return type;
+ }
+
+ set
+ {
+ type = value;
+ NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".CommandType = " + value, LogLevel.Normal);
+ }
+
+ }
+
+ IDbConnection IDbCommand.Connection
+ {
+ get
+ {
+ return Connection;
+ }
+
+ set
+ {
+ connection = (NpgsqlConnection) value;
+ NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".IDbCommand.Connection", LogLevel.Debug);
+ }
+ }
+
+ public NpgsqlConnection Connection
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg(CLASSNAME + ".get_Connection", LogLevel.Debug);
+ return connection;
+ }
+
+ set
+ {
+ connection = value;
+ NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".Connection", LogLevel.Debug);
+ }
+ }
+
+ IDataParameterCollection IDbCommand.Parameters
+ {
+ get
+ {
+ return Parameters;
+ }
+ }
+
+ public NpgsqlParameterCollection Parameters
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg(CLASSNAME + ".get_Parameters", LogLevel.Debug);
+ return parameters;
+ }
+ }
+
+ public IDbTransaction Transaction
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_Transaction()", LogLevel.Debug);
+ throw new NotImplementedException();
+ }
+
+ set
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".set_Transaction()", LogLevel.Debug);
+ throw new NotImplementedException();
+ }
+ }
+
+ public UpdateRowSource UpdatedRowSource
+ {
+ get
+ {
+
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_UpdatedRowSource()", LogLevel.Debug);
+ // [FIXME] Strange, the line below doesn't appears in the stack trace.
+
+ //throw new NotImplementedException();
+ return UpdateRowSource.Both;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void Cancel()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Cancel()", LogLevel.Debug);
+
+ // [TODO] Finish method implementation.
+ throw new NotImplementedException();
+ }
+
+
+ IDbDataParameter IDbCommand.CreateParameter()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".IDbCommand.CreateParameter()", LogLevel.Debug);
+
+ return (NpgsqlParameter) CreateParameter();
+ }
+
+ public NpgsqlParameter CreateParameter()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CreateParameter()", LogLevel.Debug);
+
+ return new NpgsqlParameter();
+ }
+
+ public Int32 ExecuteNonQuery()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteNonQuery()", LogLevel.Debug);
+
+ // Check the connection state.
+ CheckConnectionState();
+
+ if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
+ connection.Query(this);
+ else
+ throw new NotImplementedException("Only Text and StoredProcedure types supported!");
+
+
+
+ // Check if there were any errors.
+ // [FIXME] Just check the first error.
+ if (connection.Mediator.Errors.Count > 0)
+ throw new NpgsqlException(connection.Mediator.Errors[0].ToString());
+
+ // The only expected result is the CompletedResponse result.
+
+ String[] ret_string_tokens = ((String)connection.Mediator.GetCompletedResponses()[0]).Split(null); // whitespace separator.
+
+ // Check if the command was insert, delete or update.
+ // Only theses commands return rows affected.
+ // [FIXME] Is there a better way to check this??
+ if ((String.Compare(ret_string_tokens[0], "INSERT", true) == 0) ||
+ (String.Compare(ret_string_tokens[0], "UPDATE", true) == 0) ||
+ (String.Compare(ret_string_tokens[0], "DELETE", true) == 0))
+
+ // The number of rows affected is in the third token for insert queries
+ // and in the second token for update and delete queries.
+ // In other words, it is the last token in the 0-based array.
+
+ return Int32.Parse(ret_string_tokens[ret_string_tokens.Length - 1]);
+ else
+ return -1;
+
+ }
+
+ IDataReader IDbCommand.ExecuteReader()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader() implicit impl", LogLevel.Debug);
+
+ return (NpgsqlDataReader) ExecuteReader();
+ }
+
+ IDataReader IDbCommand.ExecuteReader(CommandBehavior cb)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader() implicit impl(cb)", LogLevel.Debug);
+
+ return (NpgsqlDataReader) ExecuteReader(cb);
+
+ }
+
+ public NpgsqlDataReader ExecuteReader()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader()", LogLevel.Debug);
+
+
+ return ExecuteReader(CommandBehavior.Default);
+
+ }
+
+ public NpgsqlDataReader ExecuteReader(CommandBehavior cb)
+ {
+ // [FIXME] No command behavior handling.
+
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteReader(CommandBehavior)", LogLevel.Debug);
+
+ // Check the connection state.
+ CheckConnectionState();
+
+ if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
+ connection.Query(this);
+ else
+ throw new NotImplementedException("Only Text and StoredProcedure types supported!");
+
+
+ // Check if there were any errors.
+ // [FIXME] Just check the first error.
+ if (connection.Mediator.Errors.Count > 0)
+ throw new NpgsqlException(connection.Mediator.Errors[0].ToString());
+
+
+ // Get the resultsets and create a Datareader with them.
+ return new NpgsqlDataReader(connection.Mediator.GetResultSets(), connection.Mediator.GetCompletedResponses(), connection);
+ }
+
+ public Object ExecuteScalar()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ExecuteScalar()", LogLevel.Debug);
+
+ // Check the connection state.
+ CheckConnectionState();
+
+ if ((type == CommandType.Text) || (type == CommandType.StoredProcedure))
+ connection.Query(this);
+ else
+ throw new NotImplementedException("Only Text and StoredProcedure types supported!");
+
+
+ // Check if there were any errors.
+ // [FIXME] Just check the first error.
+ if (connection.Mediator.Errors.Count > 0)
+ throw new NpgsqlException(connection.Mediator.Errors[0].ToString());
+
+
+ //ArrayList results = connection.Mediator.Data;
+
+ Object result = null; // Result of the ExecuteScalar().
+
+
+ // Now get the results.
+ // Only the first column of the first row must be returned.
+
+ // Get ResultSets.
+ ArrayList resultSets = connection.Mediator.GetResultSets();
+
+
+ // First data is the RowDescription object.
+ //NpgsqlRowDescription rd = (NpgsqlRowDescription)results[0];
+
+ NpgsqlResultSet firstResultSet = (NpgsqlResultSet)resultSets[0];
+
+ NpgsqlRowDescription rd = firstResultSet.RowDescription;
+
+ NpgsqlAsciiRow ascii_row = (NpgsqlAsciiRow)firstResultSet[0];
+
+ // Now convert the string to the field type.
+
+ // [FIXME] Hardcoded values for int types and string.
+ // Change to NpgsqlDbType.
+ // For while only int4 and string are strong typed.
+ // Any other type will be returned as string.
+
+ /*switch (rd[0].type_oid)
+ {
+ case 20: // int8, integer.
+ result = Convert.ToInt64(ascii_row[0]);
+ break;
+ case 23: // int4, integer.
+ result = Convert.ToInt32(ascii_row[0]);
+ break;
+ case 25: // text
+ // Get only the first column.
+ result = ascii_row[0];
+ break;
+ default:
+ NpgsqlEventLog.LogMsg("Unrecognized datatype returned by ExecuteScalar():" +
+ rd[0].type_oid + " Returning String...", LogLevel.Debug);
+ result = ascii_row[0];
+ break;
+ }
+
+
+ return result;*/
+
+ //return NpgsqlTypesHelper.ConvertNpgsqlTypeToSystemType(connection.OidToNameMapping, ascii_row[0], rd[0].type_oid);
+ return ascii_row[0];
+
+
+ }
+
+
+
+ public void Prepare()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Prepare()", LogLevel.Debug);
+
+
+ if (!connection.SupportsPrepare)
+ return; // Do nothing.
+
+ // Check the connection state.
+ CheckConnectionState();
+
+ // [TODO] Finish method implementation.
+ //throw new NotImplementedException();
+
+ //NpgsqlCommand command = new NpgsqlCommand("prepare plan1 as " + GetCommandText(), connection );
+ NpgsqlCommand command = new NpgsqlCommand(GetPrepareCommandText(), connection );
+ command.ExecuteNonQuery();
+
+
+
+ }
+
+ public void Dispose()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Dispose()", LogLevel.Debug);
+
+ }
+
+ ///<summary>
+ /// This method checks the connection state to see if the connection
+ /// is set or it is open. If one of this conditions is not met, throws
+ /// an InvalidOperationException
+ ///</summary>
+
+ private void CheckConnectionState()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CheckConnectionState()", LogLevel.Debug);
+
+ // Check the connection state.
+ if (connection == null)
+ throw new InvalidOperationException("The Connection is not set");
+ if (connection.State != ConnectionState.Open)
+ throw new InvalidOperationException("The Connection is not open");
+
+ }
+
+ ///<summary>
+ /// This method substitutes the parameters, if exist, in the command
+ /// to their actual values.
+ /// The parameter name format is <b>:ParameterName</b>.
+ /// </summary>
+ ///
+
+ internal String GetCommandText()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetCommandText()", LogLevel.Debug);
+
+ if (planName == String.Empty)
+ return GetClearCommandText();
+ else
+ return GetPreparedCommandText();
+
+
+ }
+
+
+ private String GetClearCommandText()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetClearCommandText()", LogLevel.Debug);
+
+
+ String result = text;
+
+ if (type == CommandType.StoredProcedure)
+ if (connection.SupportsPrepare)
+ result = "select * from " + result; // This syntax is only available in 7.3+ as well SupportsPrepare.
+ else
+ result = "select " + result; // Only a single result return supported. 7.2 and earlier.
+
+ if (parameters.Count == 0)
+ return result;
+
+
+ CheckParameters();
+
+ String parameterName;
+
+ for (Int32 i = 0; i < parameters.Count; i++)
+ {
+ parameterName = parameters[i].ParameterName;
+ //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());
+ result = result.Replace(":" + parameterName, NpgsqlTypesHelper.ConvertNpgsqlParameterToBackendStringValue(parameters[i]));
+ }
+
+ return result;
+
+ }
+
+
+
+ private String GetPreparedCommandText()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetPreparedCommandText()", LogLevel.Debug);
+
+ if (parameters.Count == 0)
+ return "execute " + planName;
+
+ CheckParameters();
+
+ StringBuilder result = new StringBuilder("execute " + planName + '(');
+
+
+ for (Int32 i = 0; i < parameters.Count; i++)
+ {
+ //result.Append(parameters[i].Value.ToString() + ',');
+ result.Append(NpgsqlTypesHelper.ConvertNpgsqlParameterToBackendStringValue(parameters[i]) + ',');
+ //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());
+ }
+
+ result = result.Remove(result.Length - 1, 1);
+ result.Append(')');
+
+ return result.ToString();
+
+ }
+
+
+ private String GetPrepareCommandText()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetPrepareCommandText()", LogLevel.Debug);
+
+
+ planName = "NpgsqlPlan" + System.Threading.Interlocked.Increment(ref planIndex);
+
+ StringBuilder command = new StringBuilder("prepare " + planName);
+
+ String textCommand = text;
+
+ if (type == CommandType.StoredProcedure)
+ textCommand = "select * from " + textCommand;
+
+
+
+ if (parameters.Count > 0)
+ {
+ CheckParameters();
+
+ command.Append('(');
+ Int32 i;
+ for (i = 0; i < parameters.Count; i++)
+ {
+ //[TODO] Add support for all types.
+
+ /*switch (parameters[i].DbType)
+ {
+ case DbType.Int32:
+ command.Append("int4");
+ break;
+
+ case DbType.Int64:
+ command.Append("int8");
+ break;
+
+ default:
+ throw new InvalidOperationException("Only DbType.Int32, DbType.Int64 datatypes supported");
+
+ }*/
+ command.Append(NpgsqlTypesHelper.GetBackendTypeNameFromDbType(parameters[i].DbType));
+
+ command.Append(',');
+ }
+
+ command = command.Remove(command.Length - 1, 1);
+ command.Append(')');
+
+
+ String parameterName;
+
+ for (i = 0; i < parameters.Count; i++)
+ {
+ //result = result.Replace(":" + parameterName, parameters[i].Value.ToString());
+ parameterName = parameters[i].ParameterName;
+ textCommand = textCommand.Replace(':' + parameterName, "$" + (i+1));
+ }
+
+ }
+
+
+ command.Append(" as ");
+ command.Append(textCommand);
+
+
+ return command.ToString();
+
+ }
+
+ private void CheckParameters()
+ {
+ String parameterName;
+
+ for (Int32 i = 0; i < parameters.Count; i++)
+ {
+ parameterName = parameters[i].ParameterName;
+ if (text.IndexOf(':' + parameterName) <= 0)
+ throw new NpgsqlException("Parameter :" + parameterName + " wasn't found in the query.");
+ }
+
+
+
+ }
+ }
+
+}
// Dave Joyner <d4ljoyn@yahoo.com>
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
"",
"");
startupPacket.WriteToStream( context.TcpClient.GetStream(), context.Encoding );
- ProcessBackendResponses( context, new ProcessBackendMessage(ProcessStartupResponses) );
- }
- private void ProcessStartupResponses( NpgsqlConnection context, Object message )
- {
-
-
+ ProcessBackendResponses( context );
}
+
}
}
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
using System.Text;
using System.Collections;
using System.Collections.Specialized;
+using NpgsqlTypes;
-// Npgsql.NpgsqlConnection
namespace Npgsql
{
/// <summary>
private readonly String CONN_DATABASE = "DATABASE";
private readonly String CONN_PORT = "PORT";
- // Postgres default port
+ // Postgres default port
private readonly String PG_PORT = "5432";
// These are for ODBC connection string compatibility
/*private BufferedStream output_stream;
private Byte[] input_buffer;*/
private Encoding connection_encoding;
-
- public NpgsqlConnection() : this(""){}
+
+ private Boolean _supportsPrepare = false;
+
+ private String _serverVersion; // Contains string returned from select version();
+
+ private Hashtable _oidToNameMapping;
+
+
+ public NpgsqlConnection() : this(String.Empty){}
public NpgsqlConnection(String ConnectionString)
{
- // NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlConnection()", LogLevel.Debug);
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlConnection()", LogLevel.Debug);
connection_state = ConnectionState.Closed;
state = NpgsqlClosedState.Instance;
connection_string = ConnectionString;
-
- connection_string_values = new ListDictionary();
-
+ connection_string_values = new ListDictionary();
connection_encoding = Encoding.Default;
_mediator = new NpgsqlMediator();
-
- if(!ConnectionString.Equals(""))
- ParseConnectionString();
+
+ _oidToNameMapping = new Hashtable();
+
+ if (connection_string != String.Empty)
+ ParseConnectionString();
}
///<value> This is the ConnectionString value </value>
{
connection_string = value;
NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".ConnectionString = " + value, LogLevel.Normal);
- ParseConnectionString();
+ if (connection_string != String.Empty)
+ ParseConnectionString();
}
}
if (connection_state == ConnectionState.Open)
throw new NpgsqlException("Connection already open");
+ if (connection_string == String.Empty)
+ throw new InvalidOperationException("ConnectionString cannot be empty.");
+
CurrentState.Open(this);
// Check if there were any errors.
if (_mediator.Errors.Count > 0)
- throw new NpgsqlException(_mediator.Errors[0].ToString());
+ {
+ StringWriter sw = new StringWriter();
+ sw.WriteLine("There have been errors on Open()");
+ uint i = 1;
+ foreach(string error in _mediator.Errors){
+ sw.WriteLine("{0}. {1}", i++, error);
+ }
+ CurrentState = NpgsqlClosedState.Instance;
+ _mediator.Reset();
+ throw new NpgsqlException(sw.ToString());
+ }
backend_keydata = _mediator.GetBackEndKeyData();
// Change the state of connection to open.
connection_state = ConnectionState.Open;
-
+
+ // Get version information to enable/disable server version features.
+ NpgsqlCommand command = new NpgsqlCommand("select version();set DATESTYLE TO ISO;", this);
+ _serverVersion = (String) command.ExecuteScalar();
+ ProcessServerVersion();
+ _oidToNameMapping = NpgsqlTypesHelper.LoadTypesMapping(this);
+
+
+
}
catch(SocketException e)
{
private void ParseConnectionString()
{
NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ParseConnectionString()", LogLevel.Debug);
-
- // Get the key-value pairs delimited by CONN_DELIM
+
+ connection_string_values.Clear();
+
+ // Get the key-value pairs delimited by CONN_DELIM
String[] pairs = connection_string.Split(new Char[] {CONN_DELIM});
String[] keyvalue;
if (connection_string_values[CONN_PORT] == null)
// Port is optional. Defaults to PG_PORT.
connection_string_values[CONN_PORT] = PG_PORT;
+
}
-
+
+
+ /// <summary>
+ /// This method is required to set all the version dependent features flags.
+ /// SupportsPrepare means the server can use prepared query plans (7.3+)
+ ///
+ /// </summary>
+
+ private void ProcessServerVersion()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ProcessServerVersion()", LogLevel.Debug);
+
+
+ SupportsPrepare = (_serverVersion.IndexOf("PostgreSQL 7.3") != -1) ||
+ (_serverVersion.IndexOf("PostgreSQL 7.4") != -1) ;
+
+ }
// State
internal void Query( NpgsqlCommand queryCommand )
{
CurrentState.Query( this, queryCommand );
}
- internal void Authenticate()
+ internal void Authenticate(string password)
{
- CurrentState.Authenticate( this );
+ CurrentState.Authenticate( this, password );
}
internal void Startup()
{
CurrentState.Startup( this );
}
+
internal NpgsqlState CurrentState
{
get
}
}
+ internal Boolean SupportsPrepare
+ {
+ get
+ {
+ return _supportsPrepare;
+ }
+
+ set
+ {
+ _supportsPrepare = value;
+ }
+ }
+
+ internal String ServerVersion
+ {
+ get
+ {
+ return _serverVersion;
+ }
+ }
+
+ internal Hashtable OidToNameMapping
+ {
+ get
+ {
+ return _oidToNameMapping;
+ }
+
+ set
+ {
+ _oidToNameMapping = value;
+ }
+
+ }
+
}
}
-
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
// Connector.cs
// ------------------------------------------------------------------
// Project
-
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
// ConnectorPool.cs
// ------------------------------------------------------------------
// Status
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Log support
private static readonly String CLASSNAME = "NpgsqlDataAdapter";
+ public NpgsqlDataAdapter() {}
+
+ public NpgsqlDataAdapter(NpgsqlCommand selectCommand)
+ {
+ _selectCommand = selectCommand;
+ }
+
+ public NpgsqlDataAdapter(String selectCommandText, NpgsqlConnection selectConnection) : this(new NpgsqlCommand(selectCommandText, selectConnection)){}
+
+ public NpgsqlDataAdapter(String selectCommandText, String selectConnectionString) : this(selectCommandText, new NpgsqlConnection(selectConnectionString)){}
+
protected override RowUpdatedEventArgs CreateRowUpdatedEvent(
DataRow dataRow,
-\r
-// Npgsql.NpgsqlDataReader.cs\r
-// \r
-// Author:\r
-// Francisco Jr. (fxjrlists@yahoo.com.br)\r
-//\r
-// Copyright (C) 2002 The Npgsql Development Team\r
-//\r
-\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.Collections;\r
-\r
-\r
-namespace Npgsql\r
-{ \r
- public class NpgsqlDataReader : IDataReader, IEnumerable\r
- {\r
- private NpgsqlConnection _connection;\r
- private ArrayList _resultsets;\r
- private ArrayList _responses;\r
- private Int32 _rowIndex;\r
- private Int32 _resultsetIndex;\r
- private NpgsqlResultSet _currentResultset;\r
- private DataTable _currentResultsetSchema;\r
- \r
- \r
- // Logging related values\r
- private static readonly String CLASSNAME = "NpgsqlDataReader";\r
- \r
- internal NpgsqlDataReader( ArrayList resultsets, ArrayList responses, NpgsqlConnection connection)\r
- {\r
- _resultsets = resultsets;\r
- _responses = responses;\r
- _connection = connection;\r
- _rowIndex = -1;\r
- _resultsetIndex = 0;\r
- \r
- _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex];\r
- \r
- \r
- \r
- }\r
- \r
- private Boolean CanRead()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CanRead() ", LogLevel.Debug);\r
- /*if (_currentResultset == null)\r
- return false;*/\r
- return (_currentResultset != null);\r
- \r
- }\r
- \r
- \r
- public void Dispose()\r
- {\r
- \r
- }\r
-\r
- public Int32 Depth \r
- {\r
- get\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_Depth() ", LogLevel.Debug);\r
- return 0;\r
- }\r
- }\r
- \r
- public Boolean IsClosed\r
- {\r
- get\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_IsClosed()", LogLevel.Debug);\r
- return false; \r
- }\r
- }\r
- \r
- public Int32 RecordsAffected \r
- {\r
- get\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_RecordsAffected()", LogLevel.Debug);\r
- \r
- /*if (_currentResultset == null)\r
- return 0; //[FIXME] Get the actual number of rows deleted, updated or inserted.\r
- return -1;\r
- */\r
- \r
- if (CanRead())\r
- return -1;\r
- \r
- String[] ret_string_tokens = ((String)_responses[_resultsetIndex]).Split(null); // whitespace separator.\r
- \r
- return Int32.Parse(ret_string_tokens[ret_string_tokens.Length - 1]);\r
- }\r
- \r
- }\r
- \r
- public void Close()\r
- {\r
- \r
- }\r
- \r
- public Boolean NextResult()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NextResult()", LogLevel.Debug);\r
- //throw new NotImplementedException();\r
- \r
- //[FIXME] Should the currentResultset not be modified\r
- // in case there aren't any more resultsets?\r
- // SqlClient modify to a invalid resultset and throws exceptions\r
- // when trying to access any data.\r
- \r
- \r
- if((_resultsetIndex + 1) < _resultsets.Count)\r
- {\r
- _resultsetIndex++;\r
- _rowIndex = -1;\r
- _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex];\r
- return true;\r
- }\r
- else\r
- return false;\r
- \r
- }\r
- \r
- public Boolean Read()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Read()", LogLevel.Debug);\r
- \r
- if (!CanRead())\r
- return false;\r
- \r
- _rowIndex++;\r
- return (_rowIndex < _currentResultset.Count);\r
- }\r
- \r
- public DataTable GetSchemaTable()\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetSchemaTable()", LogLevel.Debug);\r
- //throw new NotImplementedException();\r
- \r
- if (!CanRead())\r
- return null; //[FIXME] Should we return null or throw an exception??\r
- \r
- if(_currentResultsetSchema == null)\r
- _currentResultsetSchema = GetResultsetSchema();\r
- \r
- return _currentResultsetSchema;\r
- \r
- }\r
- \r
- \r
- public Int32 FieldCount\r
- {\r
- get\r
- {\r
- \r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_FieldCount()", LogLevel.Debug);\r
- //return ((_currentResultset == null) ? 0 : _currentResultset.RowDescription.NumFields);\r
- if (CanRead())\r
- return _currentResultset.RowDescription.NumFields;\r
- else\r
- return -1;\r
- \r
- }\r
- \r
- }\r
- \r
- public String GetName(Int32 i)\r
- {\r
- //throw new NotImplementedException();\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetName(Int32)", LogLevel.Debug);\r
- \r
- if (CanRead())\r
- return _currentResultset.RowDescription[i].name;\r
- else\r
- return String.Empty;\r
- }\r
- \r
- public String GetDataTypeName(Int32 i)\r
- {\r
- // FIXME: have a type name instead of the oid\r
- return (_currentResultset.RowDescription[i].type_oid).ToString();\r
- }\r
- \r
- public Type GetFieldType(Int32 i)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetFieldType(Int32)", LogLevel.Debug);\r
- //[FIXME] hack\r
- \r
- return Type.GetType(PGUtil.GetSystemTypeFromDbType(_currentResultset.RowDescription[i].type_oid));\r
- }\r
- \r
- public Object GetValue(Int32 i)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetValue(Int32)", LogLevel.Debug);\r
- if (i < 0 || _rowIndex < 0)\r
- throw new InvalidOperationException("Cannot read data.");\r
- return ((NpgsqlAsciiRow)_currentResultset[_rowIndex])[i];\r
- }\r
- \r
- public Int32 GetValues(Object[] values)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetValues(Object[])", LogLevel.Debug);\r
- \r
- // Only the number of elements in the array are filled.\r
- // It's also possible to pass an array with more that FieldCount elements.\r
- Int32 maxColumnIndex = (values.Length < FieldCount) ? values.Length : FieldCount;\r
- \r
- for (Int32 i = 0; i < maxColumnIndex; i++)\r
- values[i] = GetValue(i);\r
- \r
- return maxColumnIndex;\r
- \r
- }\r
- \r
- public Int32 GetOrdinal(String name)\r
- {\r
- return _currentResultset.RowDescription.FieldIndex(name);\r
- }\r
- \r
- public Object this [ Int32 i ]\r
- {\r
- get\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".this[Int32]", LogLevel.Debug);\r
- return GetValue(i);\r
- }\r
- }\r
- \r
- public Object this [ String name ]\r
- {\r
- get\r
- {\r
- //throw new NotImplementedException();\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".this[String]", LogLevel.Debug);\r
- return GetValue(_currentResultset.RowDescription.FieldIndex(name));\r
- }\r
- }\r
- \r
- public Boolean GetBoolean(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetBoolean(Int32)", LogLevel.Debug);\r
- \r
- switch ((String) this[i])\r
- {\r
- case "t":\r
- return true;\r
- \r
- case "f":\r
- return false;\r
- \r
- default:\r
- throw new System.InvalidCastException();\r
- \r
- }\r
- \r
- }\r
- \r
- public Byte GetByte(Int32 i)\r
- {\r
- throw new NotImplementedException();\r
- }\r
- \r
- public Int64 GetBytes(Int32 i, Int64 fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length)\r
- {\r
- throw new NotImplementedException();\r
- }\r
- \r
- public Char GetChar(Int32 i)\r
- {\r
- throw new NotImplementedException();\r
- }\r
- \r
- public Int64 GetChars(Int32 i, Int64 fieldoffset, Char[] buffer, Int32 bufferoffset, Int32 length)\r
- {\r
- String str;\r
-\r
- str = GetString(i);\r
- if (buffer == null)\r
- return str.Length;\r
- \r
- str.ToCharArray(bufferoffset, length).CopyTo(buffer, 0);\r
- return buffer.GetLength(0);\r
- }\r
- \r
- public Guid GetGuid(Int32 i)\r
- {\r
- throw new NotImplementedException();\r
- }\r
- \r
- public Int16 GetInt16(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt16(Int32)", LogLevel.Debug);\r
- try\r
- {\r
- return Int16.Parse((String) this[i]);\r
- } catch (System.FormatException)\r
- {\r
- throw new System.InvalidCastException();\r
- }\r
- \r
-\r
- }\r
- \r
- public Int32 GetInt32(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt32(Int32)", LogLevel.Debug);\r
- try\r
- {\r
- return Int32.Parse((String) this[i]);\r
- } catch (System.FormatException)\r
- {\r
- throw new System.InvalidCastException();\r
- }\r
- \r
-\r
- }\r
- \r
- public Int64 GetInt64(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt64(Int32)", LogLevel.Debug);\r
- try\r
- {\r
- return Int64.Parse((String) this[i]);\r
- } catch (System.FormatException)\r
- {\r
- throw new System.InvalidCastException();\r
- }\r
- }\r
- \r
- public Single GetFloat(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetFloat(Int32)", LogLevel.Debug);\r
- try\r
- {\r
- return Single.Parse((String) this[i]);\r
- } catch (System.FormatException)\r
- {\r
- throw new System.InvalidCastException();\r
- }\r
- }\r
- \r
- public Double GetDouble(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetDouble(Int32)", LogLevel.Debug);\r
- try\r
- {\r
- return Double.Parse((String) this[i]);\r
- } catch (System.FormatException)\r
- {\r
- throw new System.InvalidCastException();\r
- }\r
- }\r
- \r
- public String GetString(Int32 i)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetString(Int32)", LogLevel.Debug);\r
- return (String) GetValue(i);\r
- }\r
- \r
- public Decimal GetDecimal(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetDecimal(Int32)", LogLevel.Debug);\r
- try\r
- {\r
- return Decimal.Parse((String) this[i]);\r
- } catch (System.FormatException)\r
- {\r
- throw new System.InvalidCastException();\r
- }\r
- }\r
- \r
- public DateTime GetDateTime(Int32 i)\r
- {\r
- // Should this be done using the GetValue directly and not by converting to String\r
- // and parsing from there?\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt32(Int32)", LogLevel.Debug);\r
- try {\r
- return DateTime.ParseExact((string) this[i], "dd/MM/yyyy", null);
- } catch (System.FormatException) {\r
- throw new System.InvalidCastException();\r
- }\r
- }\r
- \r
- public IDataReader GetData(Int32 i)\r
- {\r
- throw new NotImplementedException();\r
- }\r
- \r
- public Boolean IsDBNull(Int32 i)\r
- {\r
- //throw new NotImplementedException();\r
- \r
- return ((NpgsqlAsciiRow)_currentResultset[_rowIndex]).IsNull(i);\r
- }\r
-\r
- private DataTable GetResultsetSchema()\r
- {\r
- DataTable result = null;\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetResultsetSchema()", LogLevel.Debug);\r
- // [FIXME] For now, just support fields name.\r
- \r
- NpgsqlRowDescription rd = _currentResultset.RowDescription;\r
- Int16 numFields = rd.NumFields;\r
- if(numFields > 0) {\r
- result = new DataTable("SchemaTable"); \r
-\r
+
+// Npgsql.NpgsqlDataReader.cs
+//
+// Author:
+// Francisco Jr. (fxjrlists@yahoo.com.br)
+//
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+using System;
+using System.Data;
+using System.Collections;
+using NpgsqlTypes;
+
+
+namespace Npgsql
+{
+
+ public class NpgsqlDataReader : IDataReader, IEnumerable
+ {
+
+
+
+ private NpgsqlConnection _connection;
+ private ArrayList _resultsets;
+ private ArrayList _responses;
+ private Int32 _rowIndex;
+ private Int32 _resultsetIndex;
+ private NpgsqlResultSet _currentResultset;
+ private DataTable _currentResultsetSchema;
+
+
+ // Logging related values
+ private static readonly String CLASSNAME = "NpgsqlDataReader";
+
+ internal NpgsqlDataReader( ArrayList resultsets, ArrayList responses, NpgsqlConnection connection)
+ {
+ _resultsets = resultsets;
+ _responses = responses;
+ _connection = connection;
+ _rowIndex = -1;
+ _resultsetIndex = 0;
+
+ _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex];
+
+
+
+ }
+
+ private Boolean CanRead()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CanRead() ", LogLevel.Debug);
+ /*if (_currentResultset == null)
+ return false;*/
+ return ((_currentResultset != null) && (_currentResultset.Count > 0));
+
+ }
+
+ private void CheckCanRead()
+ {
+ if (!CanRead())
+ throw new InvalidOperationException("Cannot read data");
+ }
+
+ public void Dispose()
+ {
+
+ }
+ public Int32 Depth
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_Depth() ", LogLevel.Debug);
+ return 0;
+ }
+ }
+
+ public Boolean IsClosed
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_IsClosed()", LogLevel.Debug);
+ return false;
+ }
+ }
+
+ public Int32 RecordsAffected
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_RecordsAffected()", LogLevel.Debug);
+
+ /*if (_currentResultset == null)
+ return 0; //[FIXME] Get the actual number of rows deleted, updated or inserted.
+ return -1;
+ */
+
+ if (CanRead())
+ return -1;
+
+ String[] ret_string_tokens = ((String)_responses[_resultsetIndex]).Split(null); // whitespace separator.
+
+ return Int32.Parse(ret_string_tokens[ret_string_tokens.Length - 1]);
+ }
+
+ }
+
+ public void Close()
+ {
+
+ }
+
+ public Boolean NextResult()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NextResult()", LogLevel.Debug);
+ //throw new NotImplementedException();
+
+ //[FIXME] Should the currentResultset not be modified
+ // in case there aren't any more resultsets?
+ // SqlClient modify to a invalid resultset and throws exceptions
+ // when trying to access any data.
+
+
+ if((_resultsetIndex + 1) < _resultsets.Count)
+ {
+ _resultsetIndex++;
+ _rowIndex = -1;
+ _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex];
+ return true;
+ }
+ else
+ return false;
+
+ }
+
+ public Boolean Read()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Read()", LogLevel.Debug);
+
+ if (!CanRead())
+ return false;
+
+ _rowIndex++;
+ return (_rowIndex < _currentResultset.Count);
+ }
+
+ public DataTable GetSchemaTable()
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetSchemaTable()", LogLevel.Debug);
+ //throw new NotImplementedException();
+
+ if (!CanRead())
+ return null; //[FIXME] Should we return null or throw an exception??
+
+ if(_currentResultsetSchema == null)
+ _currentResultsetSchema = GetResultsetSchema();
+
+ return _currentResultsetSchema;
+
+ }
+
+
+ public Int32 FieldCount
+ {
+ get
+ {
+
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_FieldCount()", LogLevel.Debug);
+ //return ((_currentResultset == null) ? 0 : _currentResultset.RowDescription.NumFields);
+ if (CanRead())
+ return _currentResultset.RowDescription.NumFields;
+ else
+ return -1;
+
+ }
+
+ }
+
+ public String GetName(Int32 i)
+ {
+ //throw new NotImplementedException();
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetName(Int32)", LogLevel.Debug);
+
+ if (CanRead())
+ return _currentResultset.RowDescription[i].name;
+ else
+ return String.Empty;
+ }
+
+ public String GetDataTypeName(Int32 i)
+ {
+ // FIXME: have a type name instead of the oid
+ return (_currentResultset.RowDescription[i].type_oid).ToString();
+ }
+
+ public Type GetFieldType(Int32 i)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetFieldType(Int32)", LogLevel.Debug);
+
+
+ //return Type.GetType(NpgsqlTypesHelper.GetSystemTypeNameFromTypeOid(_connection.OidToNameMapping, _currentResultset.RowDescription[i].type_oid));
+
+ return NpgsqlTypesHelper.GetSystemTypeFromTypeOid(_connection.OidToNameMapping, _currentResultset.RowDescription[i].type_oid);
+ }
+
+ public Object GetValue(Int32 i)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetValue(Int32)", LogLevel.Debug);
+
+ CheckCanRead();
+
+ if (i < 0 || _rowIndex < 0)
+ throw new InvalidOperationException("Cannot read data.");
+ return ((NpgsqlAsciiRow)_currentResultset[_rowIndex])[i];
+
+
+ }
+
+
+ public Int32 GetValues(Object[] values)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetValues(Object[])", LogLevel.Debug);
+
+ CheckCanRead();
+
+ // Only the number of elements in the array are filled.
+ // It's also possible to pass an array with more that FieldCount elements.
+ Int32 maxColumnIndex = (values.Length < FieldCount) ? values.Length : FieldCount;
+
+ for (Int32 i = 0; i < maxColumnIndex; i++)
+ values[i] = GetValue(i);
+
+ return maxColumnIndex;
+
+ }
+
+ public Int32 GetOrdinal(String name)
+ {
+ CheckCanRead();
+ return _currentResultset.RowDescription.FieldIndex(name);
+ }
+
+ public Object this [ Int32 i ]
+ {
+ get
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".this[Int32]", LogLevel.Debug);
+ return GetValue(i);
+ }
+ }
+
+ public Object this [ String name ]
+ {
+ get
+ {
+ //throw new NotImplementedException();
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".this[String]", LogLevel.Debug);
+ return GetValue(_currentResultset.RowDescription.FieldIndex(name));
+ }
+ }
+
+ public Boolean GetBoolean(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetBoolean(Int32)", LogLevel.Debug);
+
+
+ return (Boolean) GetValue(i);
+
+ }
+
+ public Byte GetByte(Int32 i)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Int64 GetBytes(Int32 i, Int64 fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Char GetChar(Int32 i)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Int64 GetChars(Int32 i, Int64 fieldoffset, Char[] buffer, Int32 bufferoffset, Int32 length)
+ {
+ String str;
+
+ str = GetString(i);
+ if (buffer == null)
+ return str.Length;
+
+ str.ToCharArray(bufferoffset, length).CopyTo(buffer, 0);
+ return buffer.GetLength(0);
+ }
+
+ public Guid GetGuid(Int32 i)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Int16 GetInt16(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt16(Int32)", LogLevel.Debug);
+ /*try
+ {
+ return Int16.Parse((String) this[i]);
+ } catch (System.FormatException)
+ {
+ throw new System.InvalidCastException();
+ }*/
+
+ return (Int16) GetValue(i);
+
+
+ }
+
+
+ public Int32 GetInt32(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt32(Int32)", LogLevel.Debug);
+ /*try
+ {
+ return Int32.Parse((String) this[i]);
+ } catch (System.FormatException)
+ {
+ throw new System.InvalidCastException();
+ }*/
+
+
+ return (Int32) GetValue(i);
+
+ }
+
+
+ public Int64 GetInt64(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt64(Int32)", LogLevel.Debug);
+ /*try
+ {
+ return Int64.Parse((String) this[i]);
+ } catch (System.FormatException)
+ {
+ throw new System.InvalidCastException();
+ }*/
+ return (Int64) GetValue(i);
+ }
+
+ public Single GetFloat(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetFloat(Int32)", LogLevel.Debug);
+ try
+ {
+ return Single.Parse((String) this[i]);
+ } catch (System.FormatException)
+ {
+ throw new System.InvalidCastException();
+ }
+ }
+
+ public Double GetDouble(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetDouble(Int32)", LogLevel.Debug);
+ try
+ {
+ return Double.Parse((String) this[i]);
+ } catch (System.FormatException)
+ {
+ throw new System.InvalidCastException();
+ }
+ }
+
+ public String GetString(Int32 i)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetString(Int32)", LogLevel.Debug);
+ return (String) GetValue(i);
+ }
+
+ public Decimal GetDecimal(Int32 i)
+ {
+ // Should this be done using the GetValue directly and not by converting to String
+ // and parsing from there?
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetDecimal(Int32)", LogLevel.Debug);
+
+
+ return (Decimal) GetValue(i);
+ }
+
+ public DateTime GetDateTime(Int32 i)
+ {
+ //throw new NotImplementedException();
+ return (DateTime) GetValue(i);
+ }
+
+ public IDataReader GetData(Int32 i)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Boolean IsDBNull(Int32 i)
+ {
+ //throw new NotImplementedException();
+
+ if (!CanRead())
+ throw new InvalidOperationException("Cannot read data");
+ return ((NpgsqlAsciiRow)_currentResultset[_rowIndex]).IsNull(i);
+ }
+
+
+
+
+
+
+ private DataTable GetResultsetSchema()
+ {
+
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetResultsetSchema()", LogLevel.Debug);
+ DataTable result = null;
+
+ NpgsqlRowDescription rd = _currentResultset.RowDescription;
+ Int16 numFields = rd.NumFields;
+ if(numFields > 0) {
+ result = new DataTable("SchemaTable");
+
result.Columns.Add ("ColumnName", typeof (string));
result.Columns.Add ("ColumnOrdinal", typeof (int));
result.Columns.Add ("ColumnSize", typeof (int));
result.Columns.Add ("IsHidden", typeof (bool));
result.Columns.Add ("IsLong", typeof (bool));
result.Columns.Add ("IsReadOnly", typeof (bool));
-\r
- DataRow row;\r
- \r
- for (Int16 i = 0; i < numFields; i++) {\r
- row = result.NewRow();\r
-\r
+
+ DataRow row;
+
+ for (Int16 i = 0; i < numFields; i++) {
+ row = result.NewRow();
+
row["ColumnName"] = GetName(i);
- row["ColumnOrdinal"] = i + 1;
+ row["ColumnOrdinal"] = i + 1;
row["ColumnSize"] = (int) rd[i].type_size;
row["NumericPrecision"] = 0;
row["NumericScale"] = 0;
row["BaseCatalogName"] = "";
row["BaseColumnName"] = GetName(i);
row["BaseSchemaName"] = "";
- row["BaseTableName"] = "";\r
+ row["BaseTableName"] = "";
row["DataType"] = GetFieldType(i);
- row["AllowDBNull"] = false;
+ row["AllowDBNull"] = false;
row["ProviderType"] = (int) rd[i].type_oid;
row["IsAliased"] = false;
row["IsExpression"] = false;
row["IsRowVersion"] = false;
row["IsHidden"] = false;
row["IsLong"] = false;
- row["IsReadOnly"] = false;\r
-\r
- result.Rows.Add(row);\r
- }\r
- }\r
- \r
- return result;\r
- \r
- }\r
-\r
- IEnumerator IEnumerable.GetEnumerator () {
+ row["IsReadOnly"] = false;
+
+ result.Rows.Add(row);
+ }
+ }
+
+ return result;
+
+ }
+
+
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
return new System.Data.Common.DbEnumerator (this);
- }\r
- }\r
-}\r
+ }
+ }
+}
// Author:
// Dave Page (dpage@postgresql.org)
//
-// Copyright (C) 2002 Dave Page
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
_rows.Add(asciiRow);
}
+ public void AddBinaryRow(NpgsqlBinaryRow asciiRow)
+ {
+ _rows.Add(asciiRow);
+ }
+
+
public void AddBackendKeydata(NpgsqlBackEndKeyData keydata)
{
_responses.Add(keydata); //hack
// Dave Joyner <d4ljoyn@yahoo.com>
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
public const Char CopyDataRows = ' ';
public const Char CopyInResponse = 'G';
public const Char CopyOutResponse = 'H';
- public const Char CursorResponse = 'B';
+ public const Char CursorResponse = 'P';
public const Char EmptyQueryResponse = 'I';
public const Char ErrorResponse = 'E';
public const Char FunctionCall = 'F';
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
using System;
using System.Data;
+using NpgsqlTypes;
+
namespace Npgsql
{
private Int32 size;
// Fields to implement IDataParameter
- private DbType type;
+ private DbType db_type;
private ParameterDirection direction;
private Boolean is_nullable;
private String name;
public NpgsqlParameter(String parameterName, DbType parameterType)
{
name = parameterName;
- type = parameterType;
+ db_type = parameterType;
+
}
public NpgsqlParameter(String parameterName, DbType parameterType, Int32 size, String sourceColumn)
{
name = parameterName;
- type = parameterType;
+ db_type = parameterType;
this.size = size;
source_column = sourceColumn;
direction = ParameterDirection.Input;
{
get
{
- return type;
+ return db_type;
}
// [TODO] Validate data type.
set
{
- type = value;
+ db_type = value;
NpgsqlEventLog.LogMsg("Set " + CLASSNAME + ".DbType = " + value, LogLevel.Normal);
}
}
+
+
public ParameterDirection Direction
{
get
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// Npgsql.NpgsqlQuery.cs\r
-// \r
-// Author:\r
-// Dave Joyner <d4ljoyn@yahoo.com>\r
-//\r
-// Copyright (C) 2002 The Npgsql Development Team\r
-//\r
-\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
-\r
-using System;\r
-using System.IO;\r
-using System.Text;\r
-using System.Net.Sockets;\r
-\r
-namespace Npgsql\r
-{\r
- /// <summary>\r
- /// Summary description for NpgsqlQuery\r
- /// </summary>\r
- internal sealed class NpgsqlQuery\r
- {\r
- private String _commandText = String.Empty;\r
- public NpgsqlQuery(String commandText)\r
- {\r
- _commandText = commandText;\r
- }\r
- public void WriteToStream( Stream outputStream, Encoding encoding )\r
- {\r
- NpgsqlEventLog.LogMsg( this.ToString() + _commandText, LogLevel.Debug );\r
- // Send the query to server.\r
- // Write the byte 'Q' to identify a query message.\r
- outputStream.WriteByte((Byte)'Q');\r
- \r
- // Write the query. In this case it is the CommandText text.\r
- // It is a string terminated by a C NULL character.\r
- outputStream.Write(encoding.GetBytes(_commandText + '\x00') , 0, encoding.GetByteCount(_commandText) + 1);\r
- \r
- \r
- \r
- }\r
- }\r
-}\r
+// Npgsql.NpgsqlQuery.cs
+//
+// Author:
+// Dave Joyner <d4ljoyn@yahoo.com>
+//
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+using System;
+using System.IO;
+using System.Text;
+using System.Net.Sockets;
+
+namespace Npgsql
+{
+ /// <summary>
+ /// Summary description for NpgsqlQuery
+ /// </summary>
+ internal sealed class NpgsqlQuery
+ {
+ private String _commandText = String.Empty;
+ public NpgsqlQuery(String commandText)
+ {
+ _commandText = commandText;
+ }
+ public void WriteToStream( Stream outputStream, Encoding encoding )
+ {
+ NpgsqlEventLog.LogMsg( this.ToString() + _commandText, LogLevel.Debug );
+ // Send the query to server.
+ // Write the byte 'Q' to identify a query message.
+ outputStream.WriteByte((Byte)'Q');
+
+ // Write the query. In this case it is the CommandText text.
+ // It is a string terminated by a C NULL character.
+ outputStream.Write(encoding.GetBytes(_commandText + '\x00') , 0, encoding.GetByteCount(_commandText) + 1);
+
+
+
+ }
+ }
+}
// Dave Joyner <d4ljoyn@yahoo.com>
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
query.WriteToStream(stream, context.Encoding);
stream.Flush();
- ProcessBackendResponses(context, new ProcessBackendMessage(ProcessQueryMessages));
+ ProcessBackendResponses(context);
}
- private void ProcessQueryMessages(NpgsqlConnection context, Object message)
- {
-
-
- }
+
}
}
// Author:
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
-// Copyright (C) 2002 Francisco Jr.
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// created on 12/6/2002 at 20:29\r
-\r
-// Npgsql.NpgsqlRowDescription.cs\r
-// \r
-// Author:\r
-// Francisco Jr. (fxjrlists@yahoo.com.br)\r
-//\r
-// Copyright (C) 2002 The Npgsql Development Team\r
-//\r
-\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
-using System;\r
-using System.Collections;\r
-using System.IO;\r
-using System.Text;\r
-using System.Net;\r
-\r
-namespace Npgsql\r
-{\r
- \r
- \r
- /// <summary>\r
- /// This struct represents the internal data of the RowDescription message.\r
- /// </summary>\r
- /// \r
- // [FIXME] Is this name OK? Does it represent well the struct intent?\r
- // Should it be a struct or a class?\r
- internal struct NpgsqlRowDescriptionFieldData\r
- {\r
- public String name;\r
- public Int32 type_oid;\r
- public Int16 type_size;\r
- public Int32 type_modifier; \r
- }\r
- \r
- /// <summary>\r
- /// This class represents a RowDescription message sent from \r
- /// the PostgreSQL.\r
- /// </summary>\r
- /// \r
- internal sealed class NpgsqlRowDescription\r
- {\r
- // Logging related values\r
- private static readonly String CLASSNAME = "NpgsqlRowDescription";\r
- \r
- \r
- private ArrayList fields_data = new ArrayList();\r
- \r
- private Hashtable fields_index = new Hashtable();\r
- \r
- \r
- public void ReadFromStream(Stream input_stream, Encoding encoding)\r
- {\r
- NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ReadFromStream()", LogLevel.Debug);\r
- \r
- Byte[] input_buffer = new Byte[10]; // Max read will be 4 + 2 + 4\r
- \r
- // Read the number of fields.\r
- input_stream.Read(input_buffer, 0, 2);\r
- Int16 num_fields = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 0));\r
- \r
- \r
- // Temporary FieldData object to get data from stream and put in array.\r
- NpgsqlRowDescriptionFieldData fd;\r
- \r
- // Now, iterate through each field getting its data.\r
- for (Int16 i = 0; i < num_fields; i++)\r
- {\r
- fd = new NpgsqlRowDescriptionFieldData();\r
- \r
- // Set field name.\r
- fd.name = PGUtil.ReadString(input_stream, encoding);\r
- \r
- // Read type_oid(Int32), type_size(Int16), type_modifier(Int32)\r
- input_stream.Read(input_buffer, 0, 4 + 2 + 4);\r
- \r
- fd.type_oid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));\r
- fd.type_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 4));\r
- fd.type_modifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 6));\r
- \r
- // Add field data to array.\r
- fields_data.Add(fd);\r
- \r
- fields_index.Add(fd.name, i);\r
- }\r
- \r
- }\r
- \r
- public NpgsqlRowDescriptionFieldData this[Int32 index]\r
- {\r
- get\r
- {\r
- return (NpgsqlRowDescriptionFieldData)fields_data[index];\r
- }\r
- \r
- }\r
- \r
- public Int16 NumFields\r
- {\r
- get\r
- {\r
- return (Int16)fields_data.Count;\r
- }\r
- }\r
- \r
- public Int16 FieldIndex(String fieldName)\r
- {\r
- return (Int16) fields_index[fieldName];\r
- }\r
- \r
- }\r
- \r
-}\r
+// created on 12/6/2002 at 20:29
+
+// Npgsql.NpgsqlRowDescription.cs
+//
+// Author:
+// Francisco Jr. (fxjrlists@yahoo.com.br)
+//
+// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+using System.Net;
+
+namespace Npgsql
+{
+
+
+ /// <summary>
+ /// This struct represents the internal data of the RowDescription message.
+ /// </summary>
+ ///
+ // [FIXME] Is this name OK? Does it represent well the struct intent?
+ // Should it be a struct or a class?
+ internal struct NpgsqlRowDescriptionFieldData
+ {
+ public String name;
+ public Int32 type_oid;
+ public Int16 type_size;
+ public Int32 type_modifier;
+ }
+
+ /// <summary>
+ /// This class represents a RowDescription message sent from
+ /// the PostgreSQL.
+ /// </summary>
+ ///
+ internal sealed class NpgsqlRowDescription
+ {
+ // Logging related values
+ private static readonly String CLASSNAME = "NpgsqlRowDescription";
+
+
+ private ArrayList fields_data = new ArrayList();
+
+ private Hashtable fields_index = new Hashtable();
+
+
+ public void ReadFromStream(Stream input_stream, Encoding encoding)
+ {
+ NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ReadFromStream()", LogLevel.Debug);
+
+ Byte[] input_buffer = new Byte[10]; // Max read will be 4 + 2 + 4
+
+ // Read the number of fields.
+ input_stream.Read(input_buffer, 0, 2);
+ Int16 num_fields = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 0));
+
+
+ // Temporary FieldData object to get data from stream and put in array.
+ NpgsqlRowDescriptionFieldData fd;
+
+ // Now, iterate through each field getting its data.
+ for (Int16 i = 0; i < num_fields; i++)
+ {
+ fd = new NpgsqlRowDescriptionFieldData();
+
+ // Set field name.
+ fd.name = PGUtil.ReadString(input_stream, encoding);
+
+ // Read type_oid(Int32), type_size(Int16), type_modifier(Int32)
+ input_stream.Read(input_buffer, 0, 4 + 2 + 4);
+
+ fd.type_oid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
+ fd.type_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 4));
+ fd.type_modifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 6));
+
+ // Add field data to array.
+ fields_data.Add(fd);
+
+ fields_index.Add(fd.name, i);
+ }
+
+ }
+
+ public NpgsqlRowDescriptionFieldData this[Int32 index]
+ {
+ get
+ {
+ return (NpgsqlRowDescriptionFieldData)fields_data[index];
+ }
+
+ }
+
+ public Int16 NumFields
+ {
+ get
+ {
+ return (Int16)fields_data.Count;
+ }
+ }
+
+ public Int16 FieldIndex(String fieldName)
+ {
+ return (Int16) fields_index[fieldName];
+ }
+
+ }
+
+}
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Dave Joyner <d4ljoyn@yahoo.com>
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
return _instance;
}
}
- public override void Authenticate( NpgsqlConnection context)
+ public override void Authenticate( NpgsqlConnection context, string password)
{
-
- NpgsqlPasswordPacket password = new NpgsqlPasswordPacket(context.ServerPassword);
+ NpgsqlEventLog.LogMsg("Entering NpgsqlStartupState.Authenticate", LogLevel.Debug);
+ NpgsqlPasswordPacket pwpck = new NpgsqlPasswordPacket(password);
BufferedStream stream = new BufferedStream(context.TcpClient.GetStream());
- password.WriteToStream(stream, context.Encoding);
+ pwpck.WriteToStream(stream, context.Encoding);
stream.Flush();
}
// Dave Joyner <d4ljoyn@yahoo.com>
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
using System.Net;
using System.Net.Sockets;
using System.Collections;
+using System.Text;
namespace Npgsql
{
public virtual void Open(NpgsqlConnection context) {}
public virtual void Startup(NpgsqlConnection context) {}
- public virtual void Authenticate(NpgsqlConnection context){}
+ public virtual void Authenticate(NpgsqlConnection context, string password){}
public virtual void Query(NpgsqlConnection context, NpgsqlCommand command) {}
public virtual void Ready( NpgsqlConnection context ) {}
- public virtual void FunctionCall(NpgsqlConnection context){}
+ public virtual void FunctionCall(NpgsqlConnection context, NpgsqlCommand command){}
public virtual void Close( NpgsqlConnection context )
context.CurrentState = newState;
}
- //public delegate void ProcessBackendMessage( NpgsqlConnection context, byte[] message );
-
- public delegate void ProcessBackendMessage( NpgsqlConnection context, Object message );
-
///<summary>
/// This method is responsible to handle all protocol messages sent from the backend.
/// It holds all the logic to do it.
- /// To exchange data, it uses a Mediator object from which it read/write information
+ /// To exchange data, it uses a Mediator object from which it reads/writes information
/// to handle backend requests.
/// </summary>
///
- protected virtual void ProcessBackendResponses( NpgsqlConnection context, ProcessBackendMessage handler )
+ protected virtual void ProcessBackendResponses( NpgsqlConnection context )
{
NetworkStream stream = context.TcpClient.GetStream();
Int32 bytesRead;
mediator.Reset();
Int16 rowDescNumFields = 0;
-
- //NpgsqlRowDescription rd = null;
- //ArrayList rows = null; // Rows associated with the row description.
-
+ NpgsqlRowDescription rd = null;
+
Byte[] inputBuffer = new Byte[ 500 ];
NpgsqlEventLog.LogMsg( this.ToString(), LogLevel.Debug);
// Send the PasswordPacket.
ChangeState( context, NpgsqlStartupState.Instance );
- context.Authenticate();
+ context.Authenticate(context.ServerPassword);
break;
}
- // Only AuthenticationClearTextPassword supported for now.
- mediator.Errors.Add("Only AuthenticationClearTextPassword supported for now.");
- return;
-
+ if ( authType == NpgsqlMessageTypes.AuthenticationMD5Password )
+ {
+ NpgsqlEventLog.LogMsg("Server requested MD5 password authentication.", LogLevel.Debug);
+ // Now do the "MD5-Thing"
+ // for this the Password has to be:
+ // 1. md5-hashed with the username as salt
+ // 2. md5-hashed again with the salt we get from the backend
+
+
+ MD5 md5 = MD5.Create();
+
+
+ // 1.
+ byte[] passwd = context.Encoding.GetBytes(context.ServerPassword);
+ byte[] saltUserName = context.Encoding.GetBytes(context.UserName);
+
+ byte[] crypt_buf = new byte[passwd.Length + saltUserName.Length];
+
+ passwd.CopyTo(crypt_buf, 0);
+ saltUserName.CopyTo(crypt_buf, passwd.Length);
+
+
+
+ StringBuilder sb = new StringBuilder ();
+ byte[] hashResult = md5.ComputeHash(crypt_buf);
+ foreach (byte b in hashResult)
+ sb.Append (b.ToString ("x2"));
+
+
+ String prehash = sb.ToString();
+
+ byte[] prehashbytes = context.Encoding.GetBytes(prehash);
+
+
+
+ byte[] saltServer = new byte[4];
+ stream.Read(saltServer, 0, 4);
+ // Send the PasswordPacket.
+ ChangeState( context, NpgsqlStartupState.Instance );
+
+
+ // 2.
+
+ crypt_buf = new byte[prehashbytes.Length + saltServer.Length];
+ prehashbytes.CopyTo(crypt_buf, 0);
+ saltServer.CopyTo(crypt_buf, prehashbytes.Length);
+
+ sb = new StringBuilder ("md5"); // This is needed as the backend expects md5 result starts with "md5"
+ hashResult = md5.ComputeHash(crypt_buf);
+ foreach (byte b in hashResult)
+ sb.Append (b.ToString ("x2"));
+
+ context.Authenticate(sb.ToString ());
+
+ break;
+ }
+
+ // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
+ mediator.Errors.Add("Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.");
+ return;
+
case NpgsqlMessageTypes.RowDescription:
// This is the RowDescription message.
- NpgsqlRowDescription rd = new NpgsqlRowDescription();
+ rd = new NpgsqlRowDescription();
rd.ReadFromStream(stream, context.Encoding);
// Initialize the array list which will contain the data from this rowdescription.
// This is the AsciiRow message.
- NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(rowDescNumFields);
+ NpgsqlAsciiRow asciiRow = new NpgsqlAsciiRow(rd, context.OidToNameMapping);
asciiRow.ReadFromStream(stream, context.Encoding);
// Now wait for CompletedResponse message.
break;
-
+ case NpgsqlMessageTypes.BinaryRow:
+
+ NpgsqlEventLog.LogMsg("BinaryRow message from Server", LogLevel.Debug);
+ NpgsqlBinaryRow binaryRow = new NpgsqlBinaryRow(rd);
+ binaryRow.ReadFromStream(stream, context.Encoding);
+
+ mediator.AddBinaryRow(binaryRow);
+
+ break;
+
case NpgsqlMessageTypes.ReadyForQuery :
NpgsqlEventLog.LogMsg("ReadyForQuery message from Server", LogLevel.Debug);
// the cursor in a FETCH case or 'blank' otherwise.
// In this case it should be always 'blank'.
// [FIXME] Get another name for this function.
-
+ NpgsqlEventLog.LogMsg("CursorResponse message from Server: ", LogLevel.Debug);
//String cursor_name = GetStringFromNetStream(networkStream);
String cursorName = PGUtil.ReadString(stream, context.Encoding);
// Continue wainting for ReadyForQuery message.
//GetStringFromNetStream(networkStream);
PGUtil.ReadString(stream, context.Encoding);
break;
+
+
}
}
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Francisco Jr. (fxjrlists@yahoo.com.br)
//
// Copyright (C) 2002 The Npgsql Development Team
+// npgsql-general@gborg.postgresql.org
+// http://gborg.postgresql.org/project/npgsql/projdisplay.php
//
-
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
using System.Net.Sockets;
using System.Net;
+
namespace Npgsql
{
///<summary>
public static void CheckedStreamRead(Stream stream, Byte[] buffer, Int32 offset, Int32 size)
{
- Int32 bytes_read = 0;
+ Int32 bytes_from_stream = 0;
+ Int32 total_bytes_read = 0;
do
{
- bytes_read = stream.Read(buffer, offset + bytes_read, size);
- size = size - bytes_read;
+ bytes_from_stream = stream.Read(buffer, offset + total_bytes_read, size);
+ total_bytes_read += bytes_from_stream;
+ size -= bytes_from_stream;
}
while(size > 0);
}
- public static String GetSystemTypeFromDbType(Int32 dbType)
- {
- // This method gets a db type identifier and return the equivalent
- // system type name.
-
- //[FIXME] Only Int32 and String supported for now.
- switch (dbType)
- {
- case 23:
- return "System.Int32";
-
- case 25:
- return "System.String";
-
- default:
- return "System.String";
-
- }
- }
+
}
}
Npgsql/AssemblyInfo.cs
+Npgsql/HashAlgorithm.cs
+Npgsql/MD5.cs
+Npgsql/MD5CryptoServiceProvider.cs
Npgsql/NpgsqlAsciiRow.cs
Npgsql/NpgsqlBackEndKeyData.cs
+Npgsql/NpgsqlBinaryRow.cs
Npgsql/NpgsqlClosedState.cs
Npgsql/NpgsqlCommand.cs
Npgsql/NpgsqlConnectedState.cs
Npgsql/NpgsqlState.cs
Npgsql/NpgsqlTransaction.cs
Npgsql/PGUtil.cs
+NpgsqlTypes/NpgsqlTypesHelper.cs