Ejemplo n.º 1
0
		internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation)
		{
			_conn = conn;
			_isolation = isolation;

			StringBuilder commandText = new StringBuilder("BEGIN; SET TRANSACTION ISOLATION LEVEL ");

			if (isolation == IsolationLevel.RepeatableRead)
			{
				commandText.Append("REPEATABLE READ");
			}
			else if ((isolation == IsolationLevel.Serializable) ||
				(isolation == IsolationLevel.Snapshot))
			{
				commandText.Append("SERIALIZABLE");
			}
			else
			{
				// Set isolation level default to read committed.
				_isolation = IsolationLevel.ReadCommitted;
				commandText.Append("READ COMMITTED");
			}

			commandText.Append(";");

			NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector);
			command.ExecuteBlind();
			_conn.Connector.Transaction = this;
		}
Ejemplo n.º 2
0
		private void _connection_Disposed(object sender, EventArgs e)
		{
			// TODO: what happens if this is called from another thread?
			// connections should not be shared across threads while in a transaction
			_connection.Disposed -= new EventHandler(_connection_Disposed);
			_connection = null;
		}
Ejemplo n.º 3
0
		/*
		 * Constructs the LargeObject API.
		 *
		 * <p><b>Important Notice</b>
		 * <br>This method should only be called by org.postgresql.Connection
		 *
		 * <p>There should only be one LargeObjectManager per Connection. The
		 * org.postgresql.Connection class keeps track of the various extension API's
		 * and it's advised you use those to gain access, and not going direct.
		 */

		public LargeObjectManager(NpgsqlConnection conn)
		{
			// We need Fastpath to do anything
			// Now get the function oid's for the api
			//
			// This is an example of Fastpath.addFunctions();
			//
			//String sql;
			StringBuilder sql = null;
			try
			{
				sql = new StringBuilder();
				if (conn.PostgreSqlVersion > new Version(7, 3, 0))
				{
					sql.Append("SELECT p.proname,p.oid ");
					sql.Append(" FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n ");
					sql.Append(" WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND (");
				}
				else
				{
					sql.Append("SELECT proname,oid FROM pg_proc WHERE ");
				}
				sql.Append(" proname = 'lo_open'");
				sql.Append(" or proname = 'lo_close'");
				sql.Append(" or proname = 'lo_creat'");
				sql.Append(" or proname = 'lo_unlink'");
				sql.Append(" or proname = 'lo_lseek'");
				sql.Append(" or proname = 'lo_tell'");
				sql.Append(" or proname = 'loread'");
				sql.Append(" or proname = 'lowrite'");

				if (conn.PostgreSqlVersion > new Version(7, 3, 0))
				{
					sql.Append(")");
				}

				using (IDbCommand cmd = new NpgsqlCommand(sql.ToString()))
				{
					cmd.Connection = conn;

					this.fp = new Fastpath(conn, conn.Connector.Stream);

					using (IDataReader res = cmd.ExecuteReader())
					{
						if (res == null)
						{
							throw new NpgsqlException("postgresql.lo.init");
						}


						fp.AddFunctions(res);
					}
				}
			}
			finally
			{
				sql = null;
			}
		}
Ejemplo n.º 4
0
		public ConnectionInfo(string connectionString)
		{
			Contract.Requires(connectionString != null);

			this.ConnectionString = connectionString;
			this.Connection = new NpgsqlConnection(connectionString);
			LastCommandTimeout = Connection.CommandTimeout;
		}
Ejemplo n.º 5
0
		private NpgsqlConnection GetConnection()
		{
			if (_connection == null || (_connection.FullState & ConnectionState.Open) != ConnectionState.Open)
			{
				_connection = new NpgsqlConnection(_connectionString);
				_connection.Open();
				_closeConnectionRequired = true;
				return _connection;
			}
			else
			{
				return _connection;
			}
		}
Ejemplo n.º 6
0
		/// <summary>
		/// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query, a <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>, and the <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see>.
		/// </summary>
		/// <param name="cmdText">The text of the query.</param>
		/// <param name="connection">A <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see> that represents the connection to a PostgreSQL server.</param>
		/// <param name="transaction">The <see cref="Npgsql.NpgsqlTransaction">NpgsqlTransaction</see> in which the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> executes.</param>
		public NpgsqlCommand(String cmdText, NpgsqlConnection connection, NpgsqlTransaction transaction)
		{
			parameters = new NpgsqlParameterCollection();
			planName = String.Empty;
			text = cmdText;
			this.connection = connection;

			if (this.connection != null)
			{
				this.m_Connector = connection.Connector;
			}

			type = CommandType.Text;
			this.Transaction = transaction;

			SetCommandTimeout();
		}
Ejemplo n.º 7
0
		/// <summary>
		/// Create a new connection based on this one.
		/// </summary>
		/// <returns>A new NpgsqlConnection object.</returns>
		public NpgsqlConnection Clone()
		{
			CheckNotDisposed();

			NpgsqlConnection C = new NpgsqlConnection(settings);

			C.Notice += this.Notice;

			if (connector != null)
			{
				C.Open();
			}

			return C;
		}
Ejemplo n.º 8
0
		private void CleanUpConnectorMethod(NpgsqlConnection Connection, NpgsqlConnector Connector)
		{
			try
			{
				Connector.CurrentReader.Close();
				Connector.CurrentReader = null;
				ReleaseConnector(Connection, Connector);
			}
			catch
			{
			}
		}
Ejemplo n.º 9
0
		private void CleanUpConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
		{
			new CleanUpConnectorDel(CleanUpConnectorMethod).BeginInvoke(Connection, Connector, null, null);
		}
Ejemplo n.º 10
0
		/*
		 * Initialises the fastpath system
		 *
		 * @param conn BaseConnection to attach to
		 * @param stream The network stream to the backend
		 */

		public Fastpath(NpgsqlConnection conn, Stream stream)
		{
			this.conn = conn;
			this.stream = stream;
		}
Ejemplo n.º 11
0
		public void Release(NpgsqlConnection connection, bool valid)
		{
			switch (Mode)
			{
				case PoolMode.None:
					try { connection.Close(); }
					catch (Exception ex)
					{
						if (valid)
							TraceSource.TraceEvent(TraceEventType.Error, 5011, "{0}", ex);
					}
					break;
				default:
					if (valid && connection.State == ConnectionState.Open && Connections.Count < Size)
					{
						Connections.Add(connection);
					}
					else
					{
						try { connection.Close(); }
						catch (Exception ex)
						{
							if (valid)
								TraceSource.TraceEvent(TraceEventType.Error, 5012, "{0}", ex);
						}
						if (Connections.Count < Size)
							Connections.Add(Info.GetConnection());
					}
					break;
			}
		}
Ejemplo n.º 12
0
		/// <summary>
		/// Cancel the transaction without telling the backend about it.  This is
		/// used to make the transaction go away when closing a connection.
		/// </summary>
		internal void Cancel()
		{
			CheckDisposed();

			if (_conn != null)
			{
				_conn.Connector.Transaction = null;
				_conn = null;
			}
		}
Ejemplo n.º 13
0
		/// <summary>
		/// Releases a connector, possibly back to the pool for future use.
		/// </summary>
		/// <remarks>
		/// Pooled connectors will be put back into the pool if there is room.
		/// Shared connectors should just have their use count decremented
		/// since they always stay in the shared pool.
		/// </remarks>
		/// <param name="Connector">The connector to release.</param>
		public void ReleaseConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
		{
			//We can only clean up a connector with a reader if the current thread hasn't been aborted
			//If it has then we need to just close it (ReleasePooledConnector will do this for an aborted thread)
			if (Connector.CurrentReader != null && (Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
			{
				CleanUpConnector(Connection, Connector);
			}
			else
			{
				ReleaseConnectorInternal(Connection, Connector);
			}
		}
Ejemplo n.º 14
0
		/// <summary>
		/// Initializes a new instance of the <see cref="Npgsql.NpgsqlCommand">NpgsqlCommand</see> class with the text of the query and a <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see>.
		/// </summary>
		/// <param name="cmdText">The text of the query.</param>
		/// <param name="connection">A <see cref="Npgsql.NpgsqlConnection">NpgsqlConnection</see> that represents the connection to a PostgreSQL server.</param>
		public NpgsqlCommand(String cmdText, NpgsqlConnection connection)
			: this(cmdText, connection, null)
		{
		}
		public NpgsqlPromotableSinglePhaseNotification(NpgsqlConnection connection)
		{
			_connection = connection;
		}
Ejemplo n.º 16
0
		internal void ClearPool(NpgsqlConnection Connection)
		{
			// Prevent multithread access to connection pool count.
			lock (locker)
			{
				ConnectorQueue queue;
				// Try to find a queue.
				if (PooledConnectors.TryGetValue(Connection.ConnectionString, out queue))
				{
					ClearQueue(queue);

					PooledConnectors.Remove(Connection.ConnectionString);
				}
			}
		}
Ejemplo n.º 17
0
		/// <summary>
		/// Put a pooled connector into the pool queue.
		/// </summary>
		/// <param name="Connector">Connector to pool</param>
		private void UngetConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
		{
			ConnectorQueue queue;

			// Find the queue.
			// As we are handling all possible queues, we have to lock everything...
			lock (locker)
			{
				PooledConnectors.TryGetValue(Connection.ConnectionString, out queue);
			}

			if (queue == null)
			{
				Connector.Close(); // Release connection to postgres
				return; // Queue may be emptied by connection problems. See ClearPool below.
			}

			Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
			Connector.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate;
			Connector.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
			Connector.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;

			bool inQueue = false;

			lock (queue)
			{
				inQueue = queue.Busy.ContainsKey(Connector);
				queue.Busy.Remove(Connector);
			}

			if (!Connector.IsInitialized)
			{
				if (Connector.Transaction != null)
				{
					Connector.Transaction.Cancel();
				}

				Connector.Close();
			}
			else
			{
				if (Connector.Transaction != null)
				{
					try
					{
						Connector.Transaction.Rollback();
					}
					catch
					{
						Connector.Close();
					}
				}
			}

			if (Connector.State == ConnectionState.Open)
			{
				//If thread is good
				if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
				{
					// Release all resources associated with this connector.
					try
					{
						Connector.ReleaseResources();
					}
					catch (Exception)
					{
						//If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue.
						// Usually it already won't be in the queue as it would of broken earlier
						inQueue = false;
					}

					if (inQueue)
						lock (queue)
						{
							queue.Available.Enqueue(Connector);
						}
					else
						Connector.Close();
				}
				else
				{
					//Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool
					Connector.Close();
				}
			}
		}
Ejemplo n.º 18
0
		/// <summary>
		/// This method is only called when NpgsqlConnection.Dispose(false) is called which means a
		/// finalization. This also means, an NpgsqlConnection was leak. We clear pool count so that
		/// client doesn't end running out of connections from pool. When the connection is finalized, its underlying
		/// socket is closed.
		/// </summary>
		public void FixPoolCountBecauseOfConnectionDisposeFalse(NpgsqlConnection Connection)
		{
			ConnectorQueue Queue;

			// Prevent multithread access to connection pool count.
			lock (locker)
			{
				// Try to find a queue.
				if (PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue) && Queue != null)
				{
					Queue.Busy.Remove(Connection.Connector);
				}
			}
		}
Ejemplo n.º 19
0
		/// <summary>
		/// Find an available pooled connector in the non-shared pool, or create
		/// a new one if none found.
		/// </summary>
		private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
		{
			ConnectorQueue Queue;
			NpgsqlConnector Connector = null;

			// We only need to lock all pools when trying to get one pool or create one.
			lock (locker)
			{
				// Try to find a queue.
				if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue))
				{
					Queue = new ConnectorQueue();
					Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
					Queue.MinPoolSize = Connection.MinPoolSize;
					PooledConnectors[Connection.ConnectionString] = Queue;
				}
			}

			// Now we can simply lock on the pool itself.
			lock (Queue)
			{
				if (Queue.Available.Count > 0)
				{
					// Found a queue with connectors.  Grab the top one.
					// Check if the connector is still valid.
					Connector = Queue.Available.Dequeue();
					Queue.Busy.Add(Connector, null);
				}
			}

			if (Connector != null)
			{
				if (!Connector.IsValid())
				{
					lock (Queue)
					{
						Queue.Busy.Remove(Connector);
					}

					Connector.Close();
					return GetPooledConnector(Connection); //Try again
				}

				return Connector;
			}

			lock (Queue)
			{
				if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize)
				{
					Connector = new NpgsqlConnector(Connection);
					Queue.Busy.Add(Connector, null);
				}
			}

			if (Connector != null)
			{
				Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
				Connector.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate;
				Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate;
				Connector.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate;

				try
				{
					Connector.Open();
				}
				catch
				{
					lock (Queue)
					{
						Queue.Busy.Remove(Connector);
					}

					Connector.Close();

					throw;
				}

				// Meet the MinPoolSize requirement if needed.
				if (Connection.MinPoolSize > 1)
				{
					lock (Queue)
					{
						while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize)
						{
							NpgsqlConnector Spare = new NpgsqlConnector(Connection);

							Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
							Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate;
							Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate;
							Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate;

							Spare.Open();

							Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
							Spare.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate;
							Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate;
							Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate;

							Queue.Available.Enqueue(Spare);
						}
					}
				}
			}

			return Connector;
		}
Ejemplo n.º 20
0
		/// <summary>
		/// Release a pooled connector.  Handle shared/non-shared here.
		/// </summary>
		private void ReleaseConnectorInternal(NpgsqlConnection Connection, NpgsqlConnector Connector)
		{
			if (!Connector.Shared)
			{
				UngetConnector(Connection, Connector);
			}
			else
			{
				// Connection sharing? What's that?
				throw new NotImplementedException("Internal: Shared pooling not implemented");
			}
		}
Ejemplo n.º 21
0
		/// <summary>
		/// Rolls back a transaction from a pending state.
		/// </summary>
		public override void Rollback()
		{
			CheckDisposed();

			if (_conn == null)
			{
				throw new InvalidOperationException(Exception_NoTransaction);
			}

			NpgsqlCommand command = new NpgsqlCommand("ROLLBACK", _conn.Connector);
			command.ExecuteBlind();
			_conn.Connector.Transaction = null;
			_conn = null;
		}
Ejemplo n.º 22
0
		private bool _disposeCopyStream; // user did not provide stream, so reset it after use

		/// <summary>
		/// Creates NpgsqlCommand to run given query upon Start(), after which CopyStream provides data from database as requested in the query.
		/// </summary>
		public NpgsqlCopyOut(string copyOutQuery, NpgsqlConnection conn)
			: this(new NpgsqlCommand(copyOutQuery, conn), conn)
		{
		}
Ejemplo n.º 23
0
		internal NpgsqlTransaction(NpgsqlConnection conn)
			: this(conn, IsolationLevel.ReadCommitted)
		{
		}
Ejemplo n.º 24
0
		/// <summary>
		/// Given command is run upon Start(), after which CopyStream provides data from database as requested in the query.
		/// </summary>
		public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn)
			: this(cmd, conn, null)
		{
		}
Ejemplo n.º 25
0
 public NpgsqlConnector(NpgsqlConnection Connection)
     : this(Connection.ConnectionStringValues.Clone(), Connection.Pooling, false)
 {
 }
Ejemplo n.º 26
0
		/// <summary>
		/// Given command is executed upon Start() and all requested copy data is written to toStream immediately.
		/// </summary>
		public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn, Stream toStream)
		{
			_context = conn.Connector;
			_cmd = cmd;
			_copyStream = toStream;
		}
Ejemplo n.º 27
0
		/*
		 * Initialises the fastpath system
		 *
		 * @param conn BaseConnection to attach to
		 * @param stream The network stream to the backend
		 */

		public Fastpath(NpgsqlConnection conn)
		{
			this.conn = conn;
			// check if the connection is closed ?
			this.stream = conn.Connector.Stream;
		}
Ejemplo n.º 28
0
		public NpgsqlTransactionCallbacks(NpgsqlConnection connection)
		{
			_connection = connection;
			_connectionString = _connection.ConnectionString;
			_connection.Disposed += new EventHandler(_connection_Disposed);
		}
Ejemplo n.º 29
0
		/// <summary>
		/// Creates an NpgsqlSchema that can read schema information from the database.
		/// </summary>
		/// <param name="connection">An open database connection for reading metadata.</param>
		internal NpgsqlSchema(NpgsqlConnection connection)
		{
			_connection = connection;
		}
Ejemplo n.º 30
0
		/// <summary>
		/// Find a pooled connector.  Handle shared/non-shared here.
		/// </summary>
		private NpgsqlConnector RequestPooledConnectorInternal(NpgsqlConnection Connection)
		{
			NpgsqlConnector Connector = null;
			Boolean Shared = false;

			// If sharing were implemented, I suppose Shared would be set based
			// on some property on the Connection.

			if (Shared)
			{
				// Connection sharing? What's that?
				throw new NotImplementedException("Internal: Shared pooling not implemented");

			}
			Connector = GetPooledConnector(Connection);


			return Connector;
		}