File:  [parser3project] / parser3 / src / include / pa_sql_connection.h
Revision 1.26: download - view: text, annotated - select for diffs - revision graph
Thu Aug 1 11:41:16 2002 UTC (23 years, 11 months ago) by paf
Branches: MAIN
CVS tags: release_3_0_0005, HEAD
$Date: now$

/** @file
	Parser: sql fconnection decl.

	Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
	Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
*/

#ifndef PA_SQL_CONNECTION_H
#define PA_SQL_CONNECTION_H

static const char* IDENT_SQL_CONNECTION_H="$Date: 2002/08/01 11:41:16 $";

#include "pa_pool.h"
#include "pa_sql_driver.h"
#include "pa_sql_driver_manager.h"

// defines

/// @see SQL_Driver_services_impl::_throw
#define SQL_CONNECTION_SERVICED_FUNC_GUARDED(actions) \
	if(!fservices || !setjmp(fservices->mark)) { \
		actions; \
	} else \
		fservices->propagate_exception();

/// SQL connection. handy wrapper around low level SQL_Driver
class SQL_Connection : public Pooled {

	friend class SQL_Connection_ptr;

public:

	SQL_Connection(Pool& pool, const String& aurl, SQL_Driver& adriver) : Pooled(pool),
		furl(aurl),
		fdriver(adriver),
		fconnection(0),
		time_used(0), used(0),
		marked_to_rollback(false) {
	}
	
	const String& get_url() { return furl; }

	void set_services(SQL_Driver_services *aservices) {
		fservices=aservices;
	}
	bool expired(time_t older_dies) {
		return !used && time_used<older_dies;
	}
	time_t get_time_used() { return time_used; }

	bool connected() { return fconnection!=0; }
	void connect(char *used_only_in_connect_url_cstr) { 
		SQL_CONNECTION_SERVICED_FUNC_GUARDED(
			fdriver.connect(used_only_in_connect_url_cstr, *fservices, &fconnection)
		);
	}
	void disconnect() { 
		fdriver.disconnect(fconnection); fconnection=0; 
	}
	bool ping() { 
		SQL_CONNECTION_SERVICED_FUNC_GUARDED(
			return fdriver.ping(*fservices, fconnection)
		);
		return 0; // never reached
	}
	uint quote(char *to, const char *from, unsigned int length) {
		SQL_CONNECTION_SERVICED_FUNC_GUARDED(
			return fdriver.quote(*fservices, fconnection, to, from, length)
		);
		return 0; // never reached
	}

	void query(
		const char *statement, unsigned long offset, unsigned long limit,
		SQL_Driver_query_event_handlers& handlers) { 
		SQL_CONNECTION_SERVICED_FUNC_GUARDED(
			fdriver.query(*fservices, fconnection, 
				statement, offset, limit, 
				handlers)
		);
	}

	void mark_to_rollback() {
		marked_to_rollback=true;
	}

private: // closing process

	void commit() { 
		SQL_CONNECTION_SERVICED_FUNC_GUARDED(
			fdriver.commit(*fservices, fconnection) 
		);
	}
	void rollback() { 
		SQL_CONNECTION_SERVICED_FUNC_GUARDED(
			fdriver.rollback(*fservices, fconnection)
		);
	}

	/// return to cache
	void close() {
		if(marked_to_rollback) {
			rollback();
			marked_to_rollback=false;
		} else
			commit();

		SQL_driver_manager->close_connection(furl, *this);
	}

private: // connection usage methods

	void use() {
		time_used=time(0); // they started to use at this time
		used++;
	}
	void unuse() {
		used--;
		if(!used)
			close();
	}

private: // connection usage data

	int used;

private:

	const String& furl;
	SQL_Driver& fdriver;
	SQL_Driver_services *fservices;
	void *fconnection;
	time_t time_used;
	bool marked_to_rollback;
};

/// Auto-object used to track SQL_Connection usage
class SQL_Connection_ptr {
	SQL_Connection *fconnection;
public:
	explicit SQL_Connection_ptr(SQL_Connection *aconnection) : fconnection(aconnection) {
		fconnection->use();
	}
	~SQL_Connection_ptr() {
		fconnection->unuse();
	}
	SQL_Connection* operator->() {
		return fconnection;
	}
	SQL_Connection* get() const {
		return fconnection; 
	}

	// copying
	SQL_Connection_ptr(const SQL_Connection_ptr& src) : fconnection(src.fconnection) {
		fconnection->use();
	}
	SQL_Connection_ptr& operator =(const SQL_Connection_ptr& src) {
		// may do without this=src check
		fconnection->unuse();
		fconnection=src.fconnection;
		fconnection->use();

		return *this;
	}
};

#endif

E-mail: