/****************************************************************************
** $Id: quickqtsql.cpp  beta1   edited Dec 10 13:07 $
**
** Copyright (C) 2001-2002 Trolltech AS.  All rights reserved.
**
** This file is part of the Qt Script for Applications framework (QSA).
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding a valid QSA Beta Evaluation Version license may use
** this file in accordance with the QSA Beta Evaluation Version License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about QSA Commercial License Agreements.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
*****************************************************************************/

#include "quickqtsql.h"
#include <qptrlist.h>
#include <qsqldatabase.h>
#include <qsqlquery.h>
#include <qsqlrecord.h>
#include <qsqlindex.h>
#include <qdatatable.h>

static QPtrList< void > ptrCleanupList;

QuickDatabase::QuickDatabase()
{
}

// Helper function that returns a pointer to the open database connection
// or NULL if it isn't open or doesn't exist
QSqlDatabase* QuickDatabase::currentConnection( const QString& database ) const
{
    QString conn = database;
    if ( conn.isEmpty() )
	conn = currentConnectionName;
    if ( conn.isEmpty() )
	return 0;
    QSqlDatabase* db = QSqlDatabase::database( conn );
    if ( !db || !db->isOpen() )
	return 0;
    return db;
}


QSqlQuery *QuickDatabase::createQuery( const QString &query, const QString &database ) const
{
    QSqlDatabase* db = currentConnection( database );
    if ( !db )
	return 0;
    QSqlQuery* q = new QSqlQuery( query, db );
    ptrCleanupList.append( (void*)q );
    return q;
}

QSqlCursor* QuickDatabase::createCursor( const QString &name, const QString &database ) const
{
    QSqlDatabase* db = currentConnection( database );
    if ( !db )
	return 0;
    QSqlCursor* c = new QSqlCursor( name, TRUE, db );
    ptrCleanupList.append( (void*)c );
    return c;
}

QSqlQuery *QuickDatabase::createQuery() const
{
    return createQuery( QString::null, QString::null );
}

QSqlQuery *QuickDatabase::createQuery( const QString &query ) const
{
    return createQuery( query, QString::null );
}

QSqlCursor* QuickDatabase::createCursor( const QString &name ) const
{
    return createCursor( name, QString::null );
}

QSqlRecord QuickDatabase::record( const QString& tablename, const QString &database ) const
{
    QSqlDatabase* db = currentConnection( database );
    if ( !db )
	return QSqlRecord();
    return db->record( tablename );
}

QSqlRecord QuickDatabase::record( const QString& tablename ) const
{
    return record( tablename, QString::null );
}


bool QuickDatabase::addConnection( const QString& databasename,
				   const QString& driver,
				   const QString& username,
				   const QString& password,
				   const QString& hostname,
				   int port )
{
    return addConnection( QSqlDatabase::defaultConnection, databasename,
			  driver, username, password, hostname, port );
}

bool QuickDatabase::addConnection( const QString& connectionname,
				   const QString& databasename,
				   const QString& driver,
				   const QString& username,
				   const QString& password,
				   const QString& hostname,
				   int port )
{
    QSqlDatabase* db =  QSqlDatabase::addDatabase( driver, connectionname );
    db->setDatabaseName( databasename );
    db->setUserName( username );
    db->setPassword( password );
    db->setHostName( hostname );
    if ( port > -1 )
	db->setPort( port );
    currentConnectionName = connectionname;
    bool b = db->open();
    if ( !b ) {
	currentConnectionName = QString::null;
	lastErrorText = db->lastError().databaseText();
	QSqlDatabase::removeDatabase( connectionname );
    }
    return b;
}

bool QuickDatabase::useDefaultConnection()
{
    return useConnection( QSqlDatabase::defaultConnection );
}

bool QuickDatabase::useConnection( const QString& name )
{
    QSqlDatabase* db = QSqlDatabase::database( name );
    if (!db || ( !db->isOpen() ) )
	return FALSE;
    currentConnectionName = name;
    return TRUE;
}

/*
void QuickDatabase::removeConnection()
{
    removeConnection( QSqlDatabase::defaultConnection );
}

void QuickDatabase::removeConnection( const QString& database )
{
    QSqlDatabase* db = QSqlDatabase::database( database );
    if ( !db )
	return;
    db->close();
    QSqlDatabase::removeDatabase( database );
}
*/

QStringList QuickDatabase::drivers() const
{
    return QSqlDatabase::drivers();
}

QStringList QuickDatabase::tables() const
{
    return tables( QString::null );
}

QStringList QuickDatabase::tables( const QString &database ) const
{
    QSqlDatabase* db = currentConnection( database );
    if ( !db )
	return QStringList();
    qDebug( "QuickDatabase::tables: " + db->tables().join( " " ) );
    return db->tables();
}

////////

QuickDatabaseQueryPtr::QuickDatabaseQueryPtr( QSqlQuery* query )
    : QuickPtrDispatchObject( "QSqlQuery", query )
{
}

QuickDatabaseQueryPtr::~QuickDatabaseQueryPtr()
{
    if ( ptrCleanupList.contains( (void*)query() ) ) {
	delete query();
	ptrCleanupList.remove( (void*)query() );
    }
}

bool QuickDatabaseQueryPtr::isValid() const
{
    return query()->isValid();
}

bool QuickDatabaseQueryPtr::isActive() const
{
    return query()->isActive();
}

bool QuickDatabaseQueryPtr::isNull( int fieldNumber ) const
{
    return query()->isNull( fieldNumber );
}

int QuickDatabaseQueryPtr::at() const
{
    return query()->at();
}

int QuickDatabaseQueryPtr::numRowsAffected() const
{
    return query()->numRowsAffected();
}

bool QuickDatabaseQueryPtr::isSelect() const
{
    return query()->isSelect();
}

int QuickDatabaseQueryPtr::size() const
{
    return query()->size();
}

bool QuickDatabaseQueryPtr::exec( const QString& newquery )
{
    return query()->exec( newquery );
}

QVariant QuickDatabaseQueryPtr::value( int i ) const
{
    return query()->value( i );
}

bool QuickDatabaseQueryPtr::seek( int recordNumber )
{
    return query()->seek( recordNumber );
}

bool QuickDatabaseQueryPtr::next()
{
    return query()->next();
}

bool QuickDatabaseQueryPtr::prev()
{
    return query()->prev();
}

bool QuickDatabaseQueryPtr::first()
{
    return query()->first();
}

bool QuickDatabaseQueryPtr::last()
{
    return query()->last();
}

QSqlQuery* QuickDatabaseQueryPtr::query() const
{
    return (QSqlQuery*)pointer();
}

////////

QuickDatabaseFieldPtr::QuickDatabaseFieldPtr( QSqlField* field )
    : QuickPtrDispatchObject( "QSqlField", field )
{
}

QuickDatabaseFieldPtr::~QuickDatabaseFieldPtr()
{
    if ( ptrCleanupList.contains( (void*)field() ) ) {
	 delete field();
	 ptrCleanupList.remove( (void*)field() );
    }
}

QVariant QuickDatabaseFieldPtr::value() const
{
    return field()->value();
}

QString QuickDatabaseFieldPtr::name() const
{
    return field()->name();
}

bool QuickDatabaseFieldPtr::isNull() const
{
    return field()->isNull();
}

QVariant::Type QuickDatabaseFieldPtr::type() const
{
    return field()->type();
}

QSqlField* QuickDatabaseFieldPtr::field() const
{
    return (QSqlField*)pointer();
}

////////

QuickDatabaseRecordPtr::QuickDatabaseRecordPtr( QSqlRecord* record )
    : QuickPtrDispatchObject( "QSqlRecord", record )
{
}

QuickDatabaseRecordPtr::~QuickDatabaseRecordPtr()
{
    if ( ptrCleanupList.contains( (void*)record() ) ) {
	delete record();
	ptrCleanupList.remove( (void*)record() );
    }
}

void QuickDatabaseRecordPtr::setValue( const QString& field, const QVariant& value )
{
    record()->setValue( field, value );
}

QVariant QuickDatabaseRecordPtr::value( const QString& field ) const
{
    return record()->value( field );
}

QString QuickDatabaseRecordPtr::fieldName( int fieldNumber ) const
{
    return record()->fieldName( fieldNumber );
}

int QuickDatabaseRecordPtr::position( const QString& field ) const
{
    return record()->position ( field );
}

QSqlField* QuickDatabaseRecordPtr::field( const QString& field )
{
    return record()->field( field );
}

bool QuickDatabaseRecordPtr::contains( const QString& field ) const
{
    return record()->contains( field );
}

void QuickDatabaseRecordPtr::clearValues()
{
    record()->clearValues();
}

void QuickDatabaseRecordPtr::nullifyValues()
{
    record()->clearValues( TRUE );
}

uint QuickDatabaseRecordPtr::count() const
{
    return record()->count();
}

QSqlRecord* QuickDatabaseRecordPtr::record() const
{
    return (QSqlRecord*)pointer();
}
//////////

QuickDatabaseIndexPtr::QuickDatabaseIndexPtr( QSqlIndex* index )
    : QuickPtrDispatchObject( "QSqlIndex", index )
{
}

QuickDatabaseIndexPtr::~QuickDatabaseIndexPtr()
{
    if ( ptrCleanupList.contains( (void*)index() ) ) {
	delete index();
	ptrCleanupList.remove( (void*)index() );
    }
}

QString QuickDatabaseIndexPtr::fieldName( int i ) const
{
    return index()->fieldName( i );
}

int QuickDatabaseIndexPtr::position( const QString& name ) const
{
    return index()->position( name );
}

bool QuickDatabaseIndexPtr::isDescending( int i )
{
    return index()->isDescending( i );
}

QVariant QuickDatabaseIndexPtr::value( int fieldNumber ) const
{
    return index()->value( fieldNumber );
}

uint QuickDatabaseIndexPtr::count() const
{
    return index()->count();
}

QSqlIndex* QuickDatabaseIndexPtr::index() const
{
    return (QSqlIndex*)pointer();
}


//////////

class QuickDatabaseCursorPtr::Private
{
public:
    QSqlIndex primaryIndex;
    QSqlIndex sort;
};

QuickDatabaseCursorPtr::QuickDatabaseCursorPtr( QSqlCursor* cursor )
    : QuickPtrDispatchObject( "QSqlCursor", cursor )
{
    d = new Private;
}

QuickDatabaseCursorPtr::~QuickDatabaseCursorPtr()
{
    if ( ptrCleanupList.contains( (void*)cursor() ) ) {
	delete cursor();
	ptrCleanupList.remove( (void*)cursor() );
    }
    delete d;
}

QVariant QuickDatabaseCursorPtr::value( const QString& field ) const
{
    return cursor()->value( field );
}

QString QuickDatabaseCursorPtr::fieldName( int fieldNumber ) const
{
    return cursor()->fieldName( fieldNumber );
}

int QuickDatabaseCursorPtr::position( const QString& field ) const
{
    return cursor()->position ( field );
}

uint QuickDatabaseCursorPtr::count() const
{
    return cursor()->count();
}

QSqlField* QuickDatabaseCursorPtr::field( const QString& field )
{
    return cursor()->field( field );
}

bool QuickDatabaseCursorPtr::contains( const QString& field ) const
{
    return cursor()->contains( field );
}

bool QuickDatabaseCursorPtr::next()
{
    return cursor()->next();
}

bool QuickDatabaseCursorPtr::prev()
{
    return cursor()->prev();
}

bool QuickDatabaseCursorPtr::first()
{
    return cursor()->first();
}

bool QuickDatabaseCursorPtr::last()
{
    return cursor()->last();
}

bool QuickDatabaseCursorPtr::seek( int recordNumber )
{
    return cursor()->seek( recordNumber );
}

QSqlIndex* QuickDatabaseCursorPtr::primaryIndex()
{
    d->primaryIndex = cursor()->primaryIndex( TRUE );
    return &d->primaryIndex;
}

QSqlRecord* QuickDatabaseCursorPtr::editBuffer()
{
    return cursor()->editBuffer();
}

QSqlRecord* QuickDatabaseCursorPtr::primeInsert()
{
    return cursor()->primeInsert();
}

QSqlRecord* QuickDatabaseCursorPtr::primeUpdate()
{
    return cursor()->primeUpdate();
}

QSqlRecord* QuickDatabaseCursorPtr::primeDelete()
{
    return cursor()->primeDelete();
}

bool QuickDatabaseCursorPtr::insertRecord()
{
    return cursor()->insert();
}

bool QuickDatabaseCursorPtr::updateRecord()
{
    return cursor()->update();
}

bool QuickDatabaseCursorPtr::deleteRecord()
{
    return cursor()->del();
}

void QuickDatabaseCursorPtr::setSort( const QString& sort )
{
    if ( !sort.length() )
	return;
    QStringList list = QStringList::split( sort, "," );
    if ( !list.count() )
	return;
    QSqlIndex s = QSqlIndex::fromStringList( list, cursor() );
    if ( s.count() )
	cursor()->setSort( s );
}

QSqlIndex* QuickDatabaseCursorPtr::sort() const
{
    return &d->sort;
}

void QuickDatabaseCursorPtr::setFilter( const QString& filter )
{
    cursor()->setFilter( filter );
}

QString QuickDatabaseCursorPtr::filter() const
{
    return cursor()->filter();
}

bool QuickDatabaseCursorPtr::selectRecords()
{
    return cursor()->select();
}

QSqlCursor* QuickDatabaseCursorPtr::cursor() const
{
    return (QSqlCursor*)pointer();
}

///////

QuickDataTableInterface::QuickDataTableInterface( QDataTable *t )
    : table( t )
{
}

QSqlRecord *QuickDataTableInterface::currentRecord() const
{
    return table->currentRecord();
}

QSqlCursor* QuickDataTableInterface::currentCursor() const
{
    table->currentRecord(); // make sure we sync to the current selection
    return table->sqlCursor();
}

QSqlCursor* QuickDataTableInterface::sqlCursor() const
{
    return table->sqlCursor();
}

bool QuickDataTableInterface::find( QSqlIndex* index )
{
    if ( !index || !table->sqlCursor() )
	return FALSE;
    QSqlCursor* cur = table->sqlCursor();
    for ( uint i = 0; i < index->count(); ++i )
	cur->editBuffer()->setValue( index->fieldName( i ), index->value( i ) );
    return table->findBuffer( *index );
}

void QuickDataTableInterface::setSqlCursor( QSqlCursor* cursor, bool autoPopulate )
{
    table->setSqlCursor( cursor, autoPopulate, FALSE );
}
