Thread: [pgsqlclient-checkins] SF.net SVN: pgsqlclient: [98] trunk/PostgreSqlClient/source/PostgreSql/Data/P
Status: Inactive
Brought to you by:
carlosga_fb
From: <car...@us...> - 2006-04-11 20:57:22
|
Revision: 98 Author: carlosga_fb Date: 2006-04-11 13:57:14 -0700 (Tue, 11 Apr 2006) ViewCVS: http://svn.sourceforge.net/pgsqlclient/?rev=98&view=rev Log Message: ----------- 2006-04-11 Carlos Guzman Alvarez (car...@te...) - Implemented Savepoint support. - Added several changes and bug fixes on database schema support. Modified Paths: -------------- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgTransaction.cs Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs 2006-04-11 20:15:14 UTC (rev 97) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs 2006-04-11 20:57:14 UTC (rev 98) @@ -254,7 +254,7 @@ #endregion - #region \xB7 Methods \xB7 + #region \xB7 Begin Transaction Methods \xB7 public new PgTransaction BeginTransaction() { @@ -263,7 +263,7 @@ public new PgTransaction BeginTransaction(IsolationLevel level) { - if (this.state == ConnectionState.Closed) + if (this.State == ConnectionState.Closed) { throw new InvalidOperationException("BeginTransaction requires an open and available Connection."); } @@ -271,7 +271,26 @@ return this.connectionInternal.BeginTransaction(level); } - public override void ChangeDatabase(string db) + public PgTransaction BeginTransaction(string transactionName) + { + return this.BeginTransaction(IsolationLevel.ReadCommitted, transactionName); + } + + public PgTransaction BeginTransaction(IsolationLevel level, string transactionName) + { + if (this.State == ConnectionState.Closed) + { + throw new InvalidOperationException("BeginTransaction requires an open and available Connection."); + } + + return this.connectionInternal.BeginTransaction(level, transactionName); + } + + #endregion + + #region \xB7 Methods \xB7 + + public override void ChangeDatabase(string db) { if (this.state == ConnectionState.Closed) { Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs 2006-04-11 20:15:14 UTC (rev 97) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs 2006-04-11 20:57:14 UTC (rev 98) @@ -154,6 +154,27 @@ return this.activeTransaction; } + public PgTransaction BeginTransaction(IsolationLevel level, string transactionName) + { + if (this.activeTransaction != null && !this.activeTransaction.IsUpdated) + { + throw new InvalidOperationException("A transaction is currently active. Parallel transactions are not supported."); + } + + try + { + this.activeTransaction = new PgTransaction(this.owningConnection, level); + this.activeTransaction.InternalBeginTransaction(); + this.activeTransaction.Save(transactionName); + } + catch (PgClientException ex) + { + throw new PgException(ex.Message, ex); + } + + return this.activeTransaction; + } + public void DisposeActiveTransaction() { // Rollback active transation Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgTransaction.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgTransaction.cs 2006-04-11 20:15:14 UTC (rev 97) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgTransaction.cs 2006-04-11 20:57:14 UTC (rev 98) @@ -137,26 +137,8 @@ #endregion - #region \xB7 Internal Methods \xB7 - - internal void InternalBeginTransaction() - { - try - { - this.connection.InternalConnection.Database.BeginTransaction(isolationLevel); + #region \xB7 DbTransaction Overriden Methods \xB7 - this.IsUpdated = false; - } - catch (PgClientException ex) - { - throw new PgException(ex.Message, ex); - } - } - - #endregion - - #region \xB7 Methods \xB7 - public override void Commit() { this.CheckTransaction(); @@ -191,6 +173,139 @@ #endregion + #region \xB7 SavePoint Methods \xB7 + + /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Save(System.String)"]/*'/> + public void Save(string savePointName) + { + lock (this) + { + if (savePointName == null) + { + throw new ArgumentException("No transaction name was be specified."); + } + else + { + if (savePointName.Length == 0) + { + throw new ArgumentException("No transaction name was be specified."); + } + } + if (this.isUpdated) + { + throw new InvalidOperationException("This Transaction has completed; it is no longer usable."); + } + + try + { + PgCommand command = new PgCommand( + "SAVEPOINT " + savePointName, + this.connection, + this); + command.ExecuteNonQuery(); + command.Dispose(); + } + catch (PgClientException ex) + { + throw new PgException(ex.Message, ex); + } + } + } + + /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Commit(System.String)"]/*'/> + public void Commit(string savePointName) + { + lock (this) + { + if (savePointName == null) + { + throw new ArgumentException("No transaction name was be specified."); + } + else + { + if (savePointName.Length == 0) + { + throw new ArgumentException("No transaction name was be specified."); + } + } + if (this.isUpdated) + { + throw new InvalidOperationException("This Transaction has completed; it is no longer usable."); + } + + try + { + PgCommand command = new PgCommand( + "RELEASE SAVEPOINT " + savePointName, + this.connection, + this); + command.ExecuteNonQuery(); + command.Dispose(); + } + catch (PgClientException ex) + { + throw new PgException(ex.Message, ex); + } + } + } + + /// <include file='Doc/en_EN/FbTransaction.xml' path='doc/class[@name="FbTransaction"]/method[@name="Rollback(System.String)"]/*'/> + public void Rollback(string savePointName) + { + lock (this) + { + if (savePointName == null) + { + throw new ArgumentException("No transaction name was be specified."); + } + else + { + if (savePointName.Length == 0) + { + throw new ArgumentException("No transaction name was be specified."); + } + } + if (this.isUpdated) + { + throw new InvalidOperationException("This Transaction has completed; it is no longer usable."); + } + + try + { + PgCommand command = new PgCommand( + "ROLLBACK WORK TO SAVEPOINT " + savePointName, + this.connection, + this); + command.ExecuteNonQuery(); + command.Dispose(); + } + catch (PgClientException ex) + { + throw new PgException(ex.Message, ex); + } + } + } + + #endregion + + #region \xB7 Internal Methods \xB7 + + internal void InternalBeginTransaction() + { + try + { + this.connection.InternalConnection.Database.BeginTransaction(isolationLevel); + + this.IsUpdated = false; + } + catch (PgClientException ex) + { + throw new PgException(ex.Message, ex); + } + } + + #endregion + #region \xB7 Private Methods \xB7 private void CheckTransaction() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2006-04-14 13:10:59
|
Revision: 116 Author: carlosga_fb Date: 2006-04-14 06:10:41 -0700 (Fri, 14 Apr 2006) ViewCVS: http://svn.sourceforge.net/pgsqlclient/?rev=116&view=rev Log Message: ----------- 2006-04-14 Carlos Guzman Alvarez (car...@te...) * Ported the connection pooling implementation from the FirebirdClient provider. * Bug fix for the Decimal parameters handling ( found running nhibernate test suite ) * Bug fix on named parameters handling. Modified Paths: -------------- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionPool.cs Added Paths: ----------- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/EmptyPoolEventHandler.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgPoolManager.cs Added: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/EmptyPoolEventHandler.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/EmptyPoolEventHandler.cs (rev 0) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/EmptyPoolEventHandler.cs 2006-04-14 13:10:41 UTC (rev 116) @@ -0,0 +1,23 @@ +/* + * PgSqlClient - ADO.NET Data Provider for PostgreSQL 7.4+ + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * Copyright (c) 2003, 2006 Carlos Guzman Alvarez + * All Rights Reserved. + */ + +using System; + +namespace PostgreSql.Data.PostgreSqlClient +{ + internal delegate void EmptyPoolEventHandler(object sender, EventArgs e); +} Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs 2006-04-13 22:33:18 UTC (rev 115) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs 2006-04-14 13:10:41 UTC (rev 116) @@ -340,21 +340,21 @@ // Open connection if (this.options.Pooling) { - this.connectionInternal = PgConnectionPool.GetConnection(this); + this.connectionInternal = PgPoolManager.Instance.GetPool(this.connectionString).CheckOut(); } else { - this.connectionInternal = new PgConnectionInternal(this); - - this.SslSetup(); - - this.connectionInternal.OwningConnection = this; + this.connectionInternal = new PgConnectionInternal(this.connectionString); this.connectionInternal.Pooled = false; - this.connectionInternal.Connect(); } + + this.SslSetup(); + this.connectionInternal.OwningConnection = this; + this.connectionInternal.Connect(); // Set connection state to Open this.state = ConnectionState.Open; + if (this.StateChange != null) { this.StateChange(this, new StateChangeEventArgs(ConnectionState.Closed, state)); @@ -402,7 +402,7 @@ // Close connection permanently or send it back to the pool if (this.connectionInternal.Pooled) { - PgConnectionPool.FreeConnection(this.connectionInternal); + PgPoolManager.Instance.GetPool(this.connectionString).CheckIn(this.connectionInternal); } else { Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs 2006-04-13 22:33:18 UTC (rev 115) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs 2006-04-14 13:10:41 UTC (rev 116) @@ -32,7 +32,8 @@ private PgConnectionOptions options; private PgTransaction activeTransaction; private ArrayList preparedCommands; - private long created; + private long created; + private long lifetime; private bool pooled; #endregion @@ -93,17 +94,23 @@ set { this.owningConnection = value; } } + public long Lifetime + { + get { return this.lifetime; } + set { this.lifetime = value; } + } + #endregion #region \xB7 Constructors \xB7 - public PgConnectionInternal(PgConnection owningConnection) + public PgConnectionInternal(string connectionString) { - this.owningConnection = owningConnection; - this.options = new PgConnectionOptions(owningConnection.ConnectionString); - this.database = new PgDatabase(this.options); - this.created = 0; - this.pooled = true; + this.options = new PgConnectionOptions(connectionString); + this.database = new PgDatabase(this.options); + this.created = 0; + this.lifetime = 0; + this.pooled = true; } #endregion @@ -123,15 +130,26 @@ } public void Disconnect() - { - try - { - this.database.Disconnect(); - } - catch (PgClientException ex) - { - throw new PgException(ex.Message, ex); - } + { + try + { + this.database.Disconnect(); + } + catch (PgClientException ex) + { + throw new PgException(ex.Message, ex); + } + finally + { + this.owningConnection = null; + this.database = null; + this.options = null; + this.activeTransaction = null; + this.preparedCommands = null; + this.created = 0; + this.lifetime = 0; + this.pooled = false; + } } public PgTransaction BeginTransaction(IsolationLevel level) Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionPool.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionPool.cs 2006-04-13 22:33:18 UTC (rev 115) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionPool.cs 2006-04-14 13:10:41 UTC (rev 116) @@ -16,224 +16,396 @@ */ using System; -using System.Data; using System.Collections; using System.Threading; +using PostgreSql.Data.Protocol; + namespace PostgreSql.Data.PostgreSqlClient { - internal class PgConnectionPool : MarshalByRefObject - { - #region \xB7 Fields \xB7 + internal sealed class PgConnectionPool : MarshalByRefObject + { + #region \xB7 Inner Types \xB7 + + private enum MoveType + { + LockedToUnlocked, + UnlockedToLocked + } - private static ConnectionPool pool = null; + #endregion + #region \xB7 Events \xB7 + + public event EmptyPoolEventHandler EmptyPool; + + #endregion + + #region \xB7 Fields \xB7 + + private PgConnectionOptions options; + private ArrayList locked; + private ArrayList unlocked; + private Thread cleanUpThread; + private string connectionString; + private bool isRunning; + private long lifeTime; + private object syncObject; + #endregion - - #region \xB7 Methods \xB7 - public static void Init() - { - if (pool == null) - { - pool = new ConnectionPool(); - } - } - - public static PgConnectionInternal GetConnection(PgConnection owningConnection) - { - Init(); + #region \xB7 Properties \xB7 - return ((PgConnectionInternal)pool.CheckOut(owningConnection)); - } + public object SyncObject + { + get + { + if (this.syncObject == null) + { + Interlocked.CompareExchange(ref this.syncObject, new object(), null); + } - public static void FreeConnection(PgConnectionInternal c) + return this.syncObject; + } + } + + public int Count { - pool.CheckIn(c); + get + { + lock (this.unlocked.SyncRoot) + { + return this.unlocked.Count + this.locked.Count; + } + } } - #endregion - } - - internal class ConnectionPool - { - #region \xB7 Fields \xB7 + public bool HasUnlocked + { + get { return this.unlocked.Count > 0; } + } - private ArrayList locked; - private ArrayList unlocked; - private Thread cleanUpThread; - #endregion #region \xB7 Constructors \xB7 - public ConnectionPool() - { - this.locked = ArrayList.Synchronized(new ArrayList()); - this.unlocked = ArrayList.Synchronized(new ArrayList()); + public PgConnectionPool(string connectionString) + { + this.connectionString = connectionString; + this.options = new PgConnectionOptions(connectionString); + this.lifeTime = this.options.ConnectionLifeTime * TimeSpan.TicksPerSecond; - this.cleanUpThread = new Thread(new ThreadStart(RunCleanUp)); - this.cleanUpThread.Name = "CleanUp Thread"; - this.cleanUpThread.Start(); - this.cleanUpThread.IsBackground = true; + if (this.options.MaxPoolSize == 0) + { + this.locked = ArrayList.Synchronized(new ArrayList()); + this.unlocked = ArrayList.Synchronized(new ArrayList()); + } + else + { + this.locked = ArrayList.Synchronized(new ArrayList(this.options.MaxPoolSize)); + this.unlocked = ArrayList.Synchronized(new ArrayList(this.options.MaxPoolSize)); + } + + // If a minimun number of connections is requested initialize the pool + this.Initialize(); + + // Start the cleanup thread only if needed + if (this.lifeTime != 0) + { + this.isRunning = true; + + this.cleanUpThread = new Thread(new ThreadStart(this.RunCleanup)); + this.cleanUpThread.Name = "Cleanup Thread"; + this.cleanUpThread.Start(); + this.cleanUpThread.IsBackground = true; + } } #endregion #region \xB7 Methods \xB7 - - public PgConnectionInternal CheckOut(PgConnection owningConnection) + + public void CheckIn(PgConnectionInternal connection) { - string connectionString = owningConnection.ConnectionString; - PgConnectionInternal newConnection = null; + connection.OwningConnection = null; + connection.Created = System.DateTime.Now.Ticks; - lock (typeof(PgConnectionPool)) + this.MoveConnection(connection, MoveType.LockedToUnlocked); + } + + public PgConnectionInternal CheckOut() + { + PgConnectionInternal newConnection = null; + + lock (this.SyncObject) + { + // 1. Try to Get a connection from the unlocked connection list. + newConnection = this.GetConnection(); + if (newConnection != null) + { + return newConnection; + } + + // 2. Check if we have reached the max number of allowed connections + this.CheckMaxPoolSize(); + + // 3. Try to Get a connection from the unlocked connection list. + newConnection = this.GetConnection(); + if (newConnection != null) + { + return newConnection; + } + + // 4. In any other case create a new connection + newConnection = this.Create(); + + // Set connection pooling settings to the new connection + newConnection.Lifetime = this.options.ConnectionLifeTime; + newConnection.Pooled = true; + + // Added to the locked connections list. + this.locked.Add(newConnection); + } + + return newConnection; + } + + public void Clear() + { + lock (this.SyncObject) { - if (this.unlocked.Count > 0) + // Stop cleanup thread + if (this.cleanUpThread != null) { - long now = System.DateTime.Now.Ticks; + this.cleanUpThread.Abort(); + this.cleanUpThread.Join(); + } - PgConnectionInternal[] list = new PgConnectionInternal[this.unlocked.Count]; - this.unlocked.CopyTo(0, list, 0, list.Length); + // Close all unlocked connections + PgConnectionInternal[] list = (PgConnectionInternal[])this.unlocked.ToArray(typeof(PgConnectionInternal)); - foreach (PgConnectionInternal connection in list) - { - if (this.Validate(connection, connectionString)) - { - if (connection.Options.ConnectionLifeTime != 0) - { - if ((now - connection.Created) > connection.Options.ConnectionLifeTime) - { - this.unlocked.Remove(connection); - this.Expire(connection); - } - else - { - this.unlocked.Remove(connection); - this.locked.Add(connection); - - connection.OwningConnection = owningConnection; - - return connection; - } - } - else - { - this.unlocked.Remove(connection); - this.locked.Add(connection); - - connection.OwningConnection = owningConnection; - - return connection; - } - } - else - { - this.unlocked.Remove(connection); - this.Expire(connection); - } - } + foreach (PgConnectionInternal connection in list) + { + connection.Disconnect(); } - newConnection = this.Create(owningConnection); - - newConnection.OwningConnection = owningConnection; - newConnection.Pooled = true; - newConnection.Created = System.DateTime.Now.Ticks; + // Close all locked connections + list = (PgConnectionInternal[])this.locked.ToArray(typeof(PgConnectionInternal)); - owningConnection.SslSetup(); + foreach (PgConnectionInternal connection in list) + { + connection.Disconnect(); + } - newConnection.Connect(); + // Clear lists + this.unlocked.Clear(); + this.locked.Clear(); - this.locked.Add(newConnection); - } - - return newConnection; - } + // Raise EmptyPool event + if (this.EmptyPool != null) + { + this.EmptyPool(this.connectionString.GetHashCode(), null); + } - public void CheckIn(PgConnectionInternal connection) - { - lock (typeof(PgConnectionPool)) - { - connection.Created = System.DateTime.Now.Ticks; - connection.OwningConnection = null; - - this.locked.Remove(connection); - this.unlocked.Add(connection); + // Reset fields + this.unlocked = null; + this.locked = null; + this.connectionString = null; + this.cleanUpThread = null; + this.EmptyPool = null; } } - #endregion + #endregion - #region \xB7 Private Methods \xB7 + #region \xB7 Private Methods \xB7 - private void RunCleanUp() - { - TimeSpan interval = new TimeSpan(0, 0, 10); + private void Initialize() + { + lock (this.SyncObject) + { + for (int i = 0; i < this.options.MinPoolSize; i++) + { + this.unlocked.Add(this.Create()); + } + } + } - while (true) - { - this.CleanUp(null); + private PgConnectionInternal Create() + { + PgConnectionInternal connection = new PgConnectionInternal(this.connectionString); + connection.Connect(); - Thread.Sleep(interval); - } + connection.Pooled = true; + connection.Created = DateTime.Now.Ticks; + + return connection; + } + + private PgConnectionInternal GetConnection() + { + PgConnectionInternal result = null; + long check = -1; + + lock (this.unlocked.SyncRoot) + { + PgConnectionInternal[] connections = (PgConnectionInternal[])this.unlocked.ToArray(typeof(PgConnectionInternal)); + + for (int i = connections.Length - 1; i >= 0; i--) + { + if (connections[i].Verify()) + { + if (this.lifeTime != 0) + { + long now = DateTime.Now.Ticks; + long expire = connections[i].Created + this.lifeTime; + + if (now >= expire) + { + if (this.CheckMinPoolSize()) + { + this.unlocked.Remove(connections[i]); + this.Expire(connections[i]); + } + } + else + { + if (expire > check) + { + check = expire; + result = connections[i]; + } + } + } + else + { + result = connections[i]; + break; + } + } + else + { + this.unlocked.Remove(connections[i]); + this.Expire(connections[i]); + } + } + + if (result != null) + { + this.MoveConnection(result, MoveType.UnlockedToLocked); + } + } + + return result; + } + + private bool CheckMinPoolSize() + { + return !(this.options.MinPoolSize > 0 && this.Count == this.options.MinPoolSize); } - private PgConnectionInternal Create(PgConnection owningConnection) + private void CheckMaxPoolSize() { - try + if (this.options.MaxPoolSize > 0 && this.Count >= this.options.MaxPoolSize) + { + long timeout = this.options.ConnectionTimeout * TimeSpan.TicksPerSecond; + long start = DateTime.Now.Ticks; + + /* + Loop brakes without errors in next situations: + 1. connection was returned from locked to unlocked by calling CheckIn in other thread (HasUnlocked = true) + 2. connection was moved from locked to unlocked (by Checkin) and then cleaned (removed from unlocked by Cleanup) + */ + while (true) + { + if (this.Count >= this.options.MaxPoolSize && this.HasUnlocked == false) + { + if ((DateTime.Now.Ticks - start) > timeout) + { + throw new SystemException("Timeout exceeded."); + } + + Thread.Sleep(100); + } + else + { + break; + } + } + } + } + + private void RunCleanup() + { + int interval = Convert.ToInt32(TimeSpan.FromTicks(this.lifeTime).TotalMilliseconds); + + if (interval > 60000) { - return new PgConnectionInternal(owningConnection); + interval = 60000; } - catch + + try { - throw; + while (this.isRunning) + { + Thread.Sleep(interval); + + this.Cleanup(); + + if (this.Count == 0) + { + lock (this.SyncObject) + { + // Empty pool + if (this.EmptyPool != null) + { + this.EmptyPool(this.connectionString.GetHashCode(), null); + } + + // Stop running + this.isRunning = false; + } + } + } } - } - - private bool Validate(PgConnectionInternal connection, string connectionString) - { - try - { - return (connection.OwningConnection.ConnectionString == connectionString && connection.Verify()); - } - catch + catch (ThreadAbortException) { - return false; + this.isRunning = false; } } private void Expire(PgConnectionInternal connection) { - try + try { if (connection.Verify()) { connection.Disconnect(); } } - catch + catch (Exception) { - throw new PgException("Error closing database connection."); + // Do not raise an exception as the connection could be invalid due to several reasons + // ( network problems, server shutdown, ... ) } } - - private void CleanUp(object State) + + private void Cleanup() { - long now = System.DateTime.Now.Ticks; - lock (this.unlocked.SyncRoot) { - if (this.unlocked.Count > 0) + if (this.unlocked.Count > 0 && this.lifeTime != 0) { - PgConnectionInternal[] list = new PgConnectionInternal[this.unlocked.Count]; - this.unlocked.CopyTo(0, list, 0, list.Length); + PgConnectionInternal[] list = (PgConnectionInternal[])this.unlocked.ToArray(typeof(PgConnectionInternal)); foreach (PgConnectionInternal connection in list) { - if (connection.Options.ConnectionLifeTime != 0) + long now = DateTime.Now.Ticks; + long expire = connection.Created + this.lifeTime; + + if (now >= expire) { - if ((now - connection.Created) >= connection.Options.ConnectionLifeTime) + if (this.CheckMinPoolSize()) { this.unlocked.Remove(connection); this.Expire(connection); @@ -244,6 +416,30 @@ } } + private void MoveConnection(PgConnectionInternal connection, MoveType moveType) + { + if (null == connection) + { + return; + } + + lock (this.unlocked.SyncRoot) + { + switch (moveType) + { + case MoveType.LockedToUnlocked: + this.locked.Remove(connection); + this.unlocked.Add(connection); + break; + + case MoveType.UnlockedToLocked: + this.unlocked.Remove(connection); + this.locked.Add(connection); + break; + } + } + } + #endregion - } + } } Added: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgPoolManager.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgPoolManager.cs (rev 0) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgPoolManager.cs 2006-04-14 13:10:41 UTC (rev 116) @@ -0,0 +1,260 @@ +/* + * PgSqlClient - ADO.NET Data Provider for PostgreSQL 7.4+ + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. + * + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * Copyright (c) 2003, 2006 Carlos Guzman Alvarez + * All Rights Reserved. + */ + +using System; +using System.Collections; +using System.Threading; + +namespace PostgreSql.Data.PostgreSqlClient +{ + internal sealed class PgPoolManager + { + #region \xB7 Static Fields \xB7 + + private static readonly PgPoolManager instance = new PgPoolManager(); + + #endregion + + #region \xB7 Static Properties \xB7 + + public static PgPoolManager Instance + { + get { return PgPoolManager.instance; } + } + + #endregion + + #region \xB7 Fields \xB7 + + private Hashtable pools; + private Hashtable handlers; + private object syncObject; + + #endregion + + #region \xB7 Properties \xB7 + + public int PoolsCount + { + get + { + if (this.pools != null) + { + return this.pools.Count; + } + return 0; + } + } + + #endregion + + #region \xB7 Private Properties \xB7 + + private Hashtable Pools + { + get + { + if (this.pools == null) + { + this.pools = Hashtable.Synchronized(new Hashtable()); + } + + return this.pools; + } + } + + private Hashtable Handlers + { + get + { + if (this.handlers == null) + { + this.handlers = Hashtable.Synchronized(new Hashtable()); + } + + return this.handlers; + } + } + + private object SyncObject + { + get + { + if (this.syncObject == null) + { + Interlocked.CompareExchange(ref this.syncObject, new object(), null); + } + + return this.syncObject; + } + } + + #endregion + + #region \xB7 Constructors \xB7 + + private PgPoolManager() + { + } + + #endregion + + #region \xB7 Methods \xB7 + + public PgConnectionPool GetPool(string connectionString) + { + PgConnectionPool pool = this.FindPool(connectionString); + + if (pool == null) + { + pool = this.CreatePool(connectionString); + } + + return pool; + } + + public PgConnectionPool FindPool(string connectionString) + { + PgConnectionPool pool = null; + + lock (this.SyncObject) + { + int hashCode = connectionString.GetHashCode(); + + if (this.Pools.ContainsKey(hashCode)) + { + pool = (PgConnectionPool)pools[hashCode]; + } + } + + return pool; + } + + public PgConnectionPool CreatePool(string connectionString) + { + PgConnectionPool pool = null; + + lock (this.SyncObject) + { + pool = this.FindPool(connectionString); + + if (pool == null) + { + lock (this.pools.SyncRoot) + { + int hashcode = connectionString.GetHashCode(); + + // Create an empty pool handler + EmptyPoolEventHandler handler = new EmptyPoolEventHandler(this.OnEmptyPool); + + this.Handlers.Add(hashcode, handler); + + // Create the new connection pool + pool = new PgConnectionPool(connectionString); + + this.pools.Add(hashcode, pool); + + pool.EmptyPool += handler; + } + } + } + + return pool; + } + + public void ClearAllPools() + { + lock (this.SyncObject) + { + lock (this.pools.SyncRoot) + { + PgConnectionPool[] tempPools = new PgConnectionPool[this.pools.Count]; + + this.pools.Values.CopyTo(tempPools, 0); + + foreach (PgConnectionPool pool in tempPools) + { + // Clear pool + pool.Clear(); + } + + // Clear Hashtables + this.pools.Clear(); + this.handlers.Clear(); + } + } + } + + public void ClearPool(string connectionString) + { + lock (this.SyncObject) + { + lock (this.pools.SyncRoot) + { + int hashCode = connectionString.GetHashCode(); + + if (this.pools.ContainsKey(hashCode)) + { + PgConnectionPool pool = (PgConnectionPool)this.pools[hashCode]; + + // Clear pool + pool.Clear(); + } + } + } + } + + public int GetPooledConnectionCount(string connectionString) + { + PgConnectionPool pool = this.FindPool(connectionString); + + return (pool != null) ? pool.Count : 0; + } + + #endregion + + #region \xB7 Event Handlers \xB7 + + private void OnEmptyPool(object sender, EventArgs e) + { + lock (this.Pools.SyncRoot) + { + int hashCode = (int)sender; + + if (this.pools.ContainsKey(hashCode)) + { + PgConnectionPool pool = (PgConnectionPool)this.Pools[hashCode]; + + lock (pool.SyncObject) + { + EmptyPoolEventHandler handler = (EmptyPoolEventHandler)this.Handlers[hashCode]; + + pool.EmptyPool -= handler; + + this.Pools.Remove(hashCode); + this.Handlers.Remove(hashCode); + + pool = null; + handler = null; + } + } + } + } + + #endregion + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2006-05-18 19:51:34
|
Revision: 145 Author: carlosga_fb Date: 2006-05-18 12:51:21 -0700 (Thu, 18 May 2006) ViewCVS: http://svn.sourceforge.net/pgsqlclient/?rev=145&view=rev Log Message: ----------- 2006-05-18 Carlos Guzman Alvarez (car...@gm...) * Added initial refcursor support for StoredProcedure calls to the PgDataReader class ( multiple refcursor's supported ). Modified Paths: -------------- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgCommand.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgCommand.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgCommand.cs 2006-05-18 19:49:14 UTC (rev 144) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgCommand.cs 2006-05-18 19:51:21 UTC (rev 145) @@ -371,7 +371,7 @@ public new PgDataReader ExecuteReader() { - return ExecuteReader(CommandBehavior.Default); + return this.ExecuteReader(CommandBehavior.Default); } public new PgDataReader ExecuteReader(CommandBehavior behavior) @@ -391,7 +391,7 @@ this.InternalExecute(); } - this.activeDataReader = new PgDataReader(this, this.connection); + this.activeDataReader = new PgDataReader(this.connection, this); return this.activeDataReader; } @@ -443,8 +443,9 @@ sql = this.BuildStoredProcedureSql(sql); } - string prepareName = "PS" + this.GetStmtName(); - string portalName = "PR" + this.GetStmtName(); + string statementName = this.GetStmtName(); + string prepareName = String.Format("PS{0}", statementName); + string portalName = String.Format("PR{0}", statementName); this.statement = conn.Database.CreateStatement(prepareName, portalName, this.ParseNamedParameters(sql)); Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs 2006-05-18 19:49:14 UTC (rev 144) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs 2006-05-18 19:51:21 UTC (rev 145) @@ -38,11 +38,13 @@ private int position; private int recordsAffected; private int fieldCount; + private object[] row; private DataTable schemaTable; private CommandBehavior behavior; private PgCommand command; private PgConnection connection; - private object[] row; + private PgStatement statement; + private Queue refCursors; #endregion @@ -62,20 +64,19 @@ #region \xB7 Constructors \xB7 - private PgDataReader() + internal PgDataReader(PgConnection connection, PgCommand command) { - this.open = true; - this.position = STARTPOS; - this.recordsAffected = -1; - this.fieldCount = -1; - } + this.open = true; + this.recordsAffected = -1; + this.position = STARTPOS; + this.fieldCount = -1; + this.refCursors = new Queue(); + this.connection = connection; + this.command = command; + this.behavior = this.command.CommandBehavior; + this.statement = this.command.Statement; - internal PgDataReader(PgCommand command, PgConnection connection) : this() - { - this.command = command; - this.behavior = this.command.CommandBehavior; - this.connection = connection; - this.fieldCount = this.command.Statement.RowDescriptor.Fields.Length; + this.Initialize(); } #endregion @@ -102,6 +103,16 @@ { // release any managed resources this.Close(); + + this.command = null; + this.statement = null; + this.connection = null; + this.refCursors = null; + this.row = null; + this.schemaTable = null; + this.fieldCount = -1; + this.recordsAffected = -1; + this.position = -1; } // release any unmanaged resources @@ -167,33 +178,60 @@ } } + this.refCursors.Clear(); + this.open = false; this.position = STARTPOS; } public override bool NextResult() { - return false; + bool hasMoreResults = false; + + if (this.refCursors.Count != 0 && this.connection.InternalConnection.HasActiveTransaction) + { + string sql = String.Format("fetch all in \"{0}\"", (string)this.refCursors.Dequeue()); + + // Reset position and field count + this.position = STARTPOS; + this.fieldCount = -1; + + // Close the active statement + this.statement.Close(); + + // Create a new statement to fetch the current refcursor + string statementName = Guid.NewGuid().ToString(); + string prepareName = String.Format("PS{0}", statementName); + string portalName = String.Format("PR{0}", statementName); + + this.statement = this.connection.InternalConnection.Database.CreateStatement(prepareName, portalName, sql); + this.statement.Parse(); + this.statement.Describe(); + this.statement.Bind(); + this.statement.Execute(); + + // Allow the DataReader to process more refcursors + hasMoreResults = true; + } + + return hasMoreResults; } public override bool Read() { bool read = false; - if ((this.behavior == CommandBehavior.SingleRow && - this.position != STARTPOS) || - !this.command.Statement.HasRows) + if ((this.behavior == CommandBehavior.SingleRow && this.position != STARTPOS) || + !this.command.Statement.HasRows) { } else { try { - this.fieldCount = this.command.Statement.RowDescriptor.Fields.Length; - this.position++; - row = this.command.Statement.FetchRow(); + row = this.statement.FetchRow(); read = (this.row == null) ? false : true; } @@ -212,11 +250,11 @@ public override DataTable GetSchemaTable() { - if (schemaTable == null) - { - schemaTable = this.GetSchemaTableStructure(); + if (this.schemaTable == null) + { + this.schemaTable = this.GetSchemaTableStructure(); - schemaTable.BeginLoadData(); + this.schemaTable.BeginLoadData(); PgCommand columnsCmd = new PgCommand(this.GetColumnsSql(), this.connection); columnsCmd.Parameters.Add("@OidNumber", PgDbType.Int4); @@ -225,16 +263,16 @@ PgCommand primaryKeyCmd = new PgCommand(this.GetPrimaryKeysSql(), this.connection); primaryKeyCmd.Parameters.Add("@OidTable", PgDbType.Int4); - for (int i = 0; i < command.Statement.RowDescriptor.Fields.Length; i++) + for (int i = 0; i < this.statement.RowDescriptor.Fields.Length; i++) { object[] columnInfo = null; Array pKeyInfo = null; // Execute commands - columnsCmd.Parameters[0].Value = command.Statement.RowDescriptor.Fields[i].OidNumber; - columnsCmd.Parameters[1].Value = command.Statement.RowDescriptor.Fields[i].OidTable; + columnsCmd.Parameters[0].Value = this.statement.RowDescriptor.Fields[i].OidNumber; + columnsCmd.Parameters[1].Value = this.statement.RowDescriptor.Fields[i].OidTable; - primaryKeyCmd.Parameters[0].Value = command.Statement.RowDescriptor.Fields[i].OidTable; + primaryKeyCmd.Parameters[0].Value = this.statement.RowDescriptor.Fields[i].OidTable; columnsCmd.InternalPrepare(); // First time it will prepare the command, next times it will close the open portal columnsCmd.InternalExecute(); @@ -256,7 +294,7 @@ } // Add row information - DataRow schemaRow = schemaTable.NewRow(); + DataRow schemaRow = this.schemaTable.NewRow(); schemaRow["ColumnName"] = this.GetName(i); schemaRow["ColumnOrdinal"] = (i + 1); @@ -301,16 +339,16 @@ schemaRow["BaseColumnName"] = System.DBNull.Value; } - schemaTable.Rows.Add(schemaRow); + this.schemaTable.Rows.Add(schemaRow); } - schemaTable.EndLoadData(); + this.schemaTable.EndLoadData(); columnsCmd.Dispose(); primaryKeyCmd.Dispose(); - } + } - return schemaTable; + return this.schemaTable; } private string GetColumnsSql() @@ -372,14 +410,22 @@ public override int FieldCount { - get { return this.command.Statement.RowDescriptor.Fields.Length; } + get + { + if (this.statement != null) + { + return this.statement.RowDescriptor.Fields.Length; + } + + return -1; + } } public override String GetName(int i) { this.CheckIndex(i); - return this.command.Statement.RowDescriptor.Fields[i].FieldName; + return this.statement.RowDescriptor.Fields[i].FieldName; } [EditorBrowsable(EditorBrowsableState.Never)] @@ -387,14 +433,14 @@ { this.CheckIndex(i); - return this.command.Statement.RowDescriptor.Fields[i].DataType.Name; + return this.statement.RowDescriptor.Fields[i].DataType.Name; } public override Type GetFieldType(int i) { this.CheckIndex(i); - return this.command.Statement.RowDescriptor.Fields[i].DataType.SystemType; + return this.statement.RowDescriptor.Fields[i].DataType.SystemType; } public override object GetValue(int i) @@ -411,7 +457,7 @@ for (int i = 0; i < this.FieldCount; i++) { - values[i] = GetValue(i); + values[i] = this.GetValue(i); } return values.Length; @@ -426,7 +472,7 @@ for (int i = 0; i < this.FieldCount; i++) { - if (this.CultureAwareCompare(command.Statement.RowDescriptor.Fields[i].FieldName, name)) + if (this.CultureAwareCompare(this.statement.RowDescriptor.Fields[i].FieldName, name)) { return i; } @@ -725,9 +771,40 @@ #region \xB7 Private Methods \xB7 + private void Initialize() + { + if (this.connection.InternalConnection.HasActiveTransaction) + { + // Ref cursors can be fetched only if there are an active transaction + if (this.command.CommandType == CommandType.StoredProcedure && + this.command.Statement.RowDescriptor.Fields.Length == 1 && + this.command.Statement.RowDescriptor.Fields[0].DataType.IsRefCursor) + { + // Clear refcursor's queue + this.refCursors.Clear(); + + // Add refcrusr's names to the queue + object[] row = new object[0]; + + while (row != null) + { + row = this.statement.FetchRow(); + + if (row != null) + { + this.refCursors.Enqueue(row[0]); + } + } + + // Grab information of the first refcursor + this.NextResult(); + } + } + } + private void CheckIndex(int i) { - if (i < 0 || i >= this.fieldCount) + if (i < 0 || i >= this.FieldCount) { throw new IndexOutOfRangeException("Could not find specified column in results."); } @@ -770,7 +847,7 @@ throw new IndexOutOfRangeException("Could not find specified column in results."); } - return this.command.Statement.RowDescriptor.Fields[i].DataType.IsNumeric(); + return this.command.Statement.RowDescriptor.Fields[i].DataType.IsNumeric; } private bool IsLong(int i) @@ -780,7 +857,7 @@ throw new IndexOutOfRangeException("Could not find specified column in results."); } - return this.command.Statement.RowDescriptor.Fields[i].DataType.IsLong(); + return this.command.Statement.RowDescriptor.Fields[i].DataType.IsLong; } private bool IsAliased(int i) Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs 2006-05-18 19:49:14 UTC (rev 144) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs 2006-05-18 19:51:21 UTC (rev 145) @@ -44,6 +44,7 @@ Path , Point , Polygon , + Refcursor , Text , Time , TimeWithTZ , This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2006-05-31 18:36:44
|
Revision: 167 Author: carlosga_fb Date: 2006-05-31 11:36:25 -0700 (Wed, 31 May 2006) ViewCVS: http://svn.sourceforge.net/pgsqlclient/?rev=167&view=rev Log Message: ----------- 2006-05-31 Carlos Guzman Alvarez (car...@gm...) - Committed initial support for fetching PostGIS Box2D values. Modified Paths: -------------- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs 2006-05-31 18:35:53 UTC (rev 166) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDataReader.cs 2006-05-31 18:36:25 UTC (rev 167) @@ -307,9 +307,9 @@ schemaRow["NumericScale"] = DBNull.Value; } schemaRow["DataType"] = this.GetFieldType(i); - schemaRow["ProviderType"] = this.GetProviderType(i); + schemaRow["ProviderType"] = this.GetProviderDbType(i); schemaRow["IsLong"] = this.IsLong(i); - schemaRow["IsRowVersion"] = false; + schemaRow["IsRowVersion"] = this.CultureAwareCompare(this.GetName(i), "oid"); schemaRow["IsUnique"] = false; schemaRow["IsAliased"] = this.IsAliased(i); schemaRow["IsExpression"] = this.IsExpression(i); @@ -664,12 +664,22 @@ return (TimeSpan)GetValue(i); } - public PgPoint GetPgPoint(int i) + public PgTimeSpan GetPgTimeSpan(int i) + { + this.CheckPosition(); + this.CheckIndex(i); + + return new PgTimeSpan(this.GetTimeSpan(i)); + } + + #region \xB7 Geometric Types \xB7 + + public PgPoint GetPgPoint(int i) { this.CheckPosition(); this.CheckIndex(i); - return (PgPoint)this.GetPgValue(i); + return (PgPoint)this.GetProviderSpecificValue(i); } public PgBox GetPgBox(int i) @@ -677,7 +687,7 @@ this.CheckPosition(); this.CheckIndex(i); - return (PgBox)this.GetPgValue(i); + return (PgBox)this.GetProviderSpecificValue(i); } public PgLSeg GetPgLSeg(int i) @@ -685,7 +695,7 @@ this.CheckPosition(); this.CheckIndex(i); - return (PgLSeg)this.GetPgValue(i); + return (PgLSeg)this.GetProviderSpecificValue(i); } public PgCircle GetPgCircle(int i) @@ -693,7 +703,7 @@ this.CheckPosition(); this.CheckIndex(i); - return (PgCircle)this.GetPgValue(i); + return (PgCircle)this.GetProviderSpecificValue(i); } public PgPath GetPgPath(int i) @@ -701,7 +711,7 @@ this.CheckPosition(); this.CheckIndex(i); - return (PgPath)this.GetPgValue(i); + return (PgPath)this.GetProviderSpecificValue(i); } public PgPolygon GetPgPolygon(int i) @@ -709,23 +719,34 @@ this.CheckPosition(); this.CheckIndex(i); - return (PgPolygon)this.GetPgValue(i); - } + return (PgPolygon)this.GetProviderSpecificValue(i); + } - public PgTimeSpan GetPgTimeSpan(int i) - { - this.CheckPosition(); - this.CheckIndex(i); + #endregion - return new PgTimeSpan(this.GetTimeSpan(i)); - } + #region \xB7 PostGIS Types \xB7 - public object GetPgValue(int i) + public PgBox2D GetPgBox2D(int i) + { + this.CheckPosition(); + this.CheckIndex(i); + + return (PgBox2D)this.GetProviderSpecificValue(i); + } + + #endregion + + public override Type GetProviderSpecificFieldType(int i) + { + return this.GetFieldType(i); + } + + public override object GetProviderSpecificValue(int i) { this.CheckPosition(); this.CheckIndex(i); - switch (this.GetProviderType(i)) + switch (this.GetProviderDbType(i)) { case PgDbType.Interval: return this.GetPgTimeSpan(i); @@ -735,7 +756,7 @@ } } - public int GetPgValues(object[] values) + public override int GetProviderSpecificValues(object[] values) { return this.GetValues(values); } @@ -820,6 +841,11 @@ return this.command.Statement.RowDescriptor.Fields[i].DataType.Size; } + private PgDbType GetProviderDbType(int i) + { + return (PgDbType)this.command.Statement.RowDescriptor.Fields[i].DataType.DataType; + } + private int GetNumericPrecision(int i) { #warning "Add implementation" @@ -832,11 +858,6 @@ return 0; } - private PgDbType GetProviderType(int i) - { - return (PgDbType)this.command.Statement.RowDescriptor.Fields[i].DataType.DataType; - } - private bool IsNumeric(int i) { if (i < 0 || i >= this.FieldCount) @@ -916,6 +937,11 @@ } } + private bool IsCommandBehavior(CommandBehavior behavior) + { + return ((behavior & this.behavior) == behavior); + } + private bool CultureAwareCompare(string strA, string strB) { return CultureInfo.CurrentCulture.CompareInfo.Compare( Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs 2006-05-31 18:35:53 UTC (rev 166) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgDbType.cs 2006-05-31 18:36:25 UTC (rev 167) @@ -26,7 +26,9 @@ Binary , Boolean , Box , - Byte , + Box2D , + Box3D , + Byte , Char , Circle , Currency , This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2006-06-26 16:00:55
|
Revision: 175 Author: carlosga_fb Date: 2006-06-26 09:00:41 -0700 (Mon, 26 Jun 2006) ViewCVS: http://svn.sourceforge.net/pgsqlclient/?rev=175&view=rev Log Message: ----------- Changes on internal data type handling Modified Paths: -------------- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionStringBuilder.cs Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs 2006-06-19 21:31:25 UTC (rev 174) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnection.cs 2006-06-26 16:00:41 UTC (rev 175) @@ -360,6 +360,9 @@ this.StateChange(this, new StateChangeEventArgs(ConnectionState.Closed, state)); } + // Grab Data Types Oid's from the database if requested + this.connectionInternal.FetchDatabaseOids(); + // Add Info message event handler this.connectionInternal.Database.InfoMessage = new InfoMessageCallback(this.OnInfoMessage); Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs 2006-06-19 21:31:25 UTC (rev 174) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionInternal.cs 2006-06-26 16:00:41 UTC (rev 175) @@ -257,6 +257,38 @@ return isValid; } + internal void FetchDatabaseOids() + { + if (this.database.Options.UseDatabaseOids) + { + string sql = "SELECT oid FROM pg_type WHERE typname=@typeName"; + + if (this.owningConnection != null) + { + PgCommand command = new PgCommand(sql, this.owningConnection); + command.Parameters.Add("@typeName", PgDbType.VarChar); + + // After the connection gets established we should update the Data Types collection oids + foreach (PgType type in this.Database.DataTypes) + { + command.Parameters["@typeName"].Value = type.Name; + + object realOid = command.ExecuteScalar(); + + if (realOid != null) + { + if (Convert.ToInt32(realOid) != type.Oid) + { + type.UpdateOid(Convert.ToInt32(realOid)); + } + } + } + + command.Dispose(); + } + } + } + #endregion - } + } } \ No newline at end of file Modified: trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionStringBuilder.cs =================================================================== --- trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionStringBuilder.cs 2006-06-19 21:31:25 UTC (rev 174) +++ trunk/PostgreSqlClient/source/PostgreSql/Data/PostgreSqlClient/PgConnectionStringBuilder.cs 2006-06-26 16:00:41 UTC (rev 175) @@ -55,6 +55,7 @@ synonyms.Add("min pool size", "min pool size"); synonyms.Add("max pool size", "max pool size"); synonyms.Add("ssl", "ssl"); + synonyms.Add("use database oids", "use database oids"); return synonyms; } @@ -135,8 +136,14 @@ set { this.SetValue("Ssl", value); } } - #endregion + public bool UseDatabaseOids + { + get { return this.GetBoolean("use database oids"); } + set { this.SetValue("use database oids", value); } + } + #endregion + #region \xB7 Constructors \xB7 public PgConnectionStringBuilder() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |