예제 #1
0
bool KexiMigrate::checkIfDestinationDatabaseOverwritingNeedsAccepting(Kexi::ObjectStatus* result,
        bool& acceptingNeeded)
{
    acceptingNeeded = false;
    if (result)
        result->clearStatus();

    KexiDB::DriverManager drvManager;
    KexiDB::Driver *destDriver = drvManager.driver(
                                     m_migrateData->destination->connectionData()->driverName);
    if (!destDriver) {
        result->setStatus(&drvManager,
                          i18n("Could not create database \"%1\".",
                               m_migrateData->destination->databaseName()));
        return false;
    }

    // For file-based dest. projects, we've already asked about overwriting
    // existing project but for server-based projects we need to ask now.
    if (destDriver->isFileDriver())
        return true; //nothing to check
    KexiDB::Connection *tmpConn
    = destDriver->createConnection(*m_migrateData->destination->connectionData());
    if (!tmpConn || destDriver->error() || !tmpConn->connect()) {
        delete tmpConn;
        return true;
    }
    if (tmpConn->databaseExists(m_migrateData->destination->databaseName())) {
        acceptingNeeded = true;
    }
    tmpConn->disconnect();
    delete tmpConn;
    return true;
}
예제 #2
0
void ConnectionTestThread::run()
{
    KexiDB::DriverManager manager;
    KexiDB::Driver* drv = manager.driver(m_connData.driverName);
// KexiGUIMessageHandler msghdr;
    if (!drv || manager.error()) {
//move  msghdr.showErrorMessage(&Kexi::driverManager());
        m_dlg->error(&manager);
        return;
    }
    KexiDB::Connection * conn = drv->createConnection(m_connData);
    if (!conn || drv->error()) {
//move  msghdr.showErrorMessage(drv);
        delete conn;
        m_dlg->error(drv);
        return;
    }
    if (!conn->connect() || conn->error()) {
//move  msghdr.showErrorMessage(conn);
        m_dlg->error(conn);
        delete conn;
        return;
    }
    // SQL database backends like PostgreSQL require executing "USE database"
    // if we really want to know connection to the server succeeded.
    QString tmpDbName;
    if (!conn->useTemporaryDatabaseIfNeeded(tmpDbName)) {
        m_dlg->error(conn);
        delete conn;
        return;
    }
    delete conn;
    m_dlg->error(0);
}
예제 #3
0
//===========================================================
//
void ImportWizard::setupDstType()
{
	m_dstTypePage = new QWidget(this);

	KexiDB::DriverManager manager;
	KexiDB::Driver::InfoMap drvs = manager.driversInfo();

	QVBoxLayout *vbox = new QVBoxLayout(m_dstTypePage, KDialog::marginHint());

	QHBoxLayout *hbox = new QHBoxLayout(vbox);
	QLabel *lbl = new QLabel(i18n("Destination database type:")+" ", m_dstTypePage);
	lbl->setAlignment(Qt::AlignAuto|Qt::AlignTop);
	hbox->addWidget(lbl);

	m_dstPrjTypeSelector = new KexiPrjTypeSelector(m_dstTypePage);
	hbox->addWidget(m_dstPrjTypeSelector);
	m_dstPrjTypeSelector->option_file->setText(i18n("Database project stored in a file"));
	m_dstPrjTypeSelector->option_server->setText(i18n("Database project stored on a server"));

	QVBoxLayout *frame_server_vbox = new QVBoxLayout(m_dstPrjTypeSelector->frame_server, KDialog::spacingHint());
	m_dstServerTypeCombo = new KexiDBDriverComboBox(m_dstPrjTypeSelector->frame_server, drvs, 
		KexiDBDriverComboBox::ShowServerDrivers);
	frame_server_vbox->addWidget(m_dstServerTypeCombo);
	hbox->addStretch(1);
	vbox->addStretch(1);
	lbl->setBuddy(m_dstServerTypeCombo);

//! @todo hardcoded: find a way to preselect default engine item
	//m_dstTypeCombo->setCurrentText("SQLite3");
	addPage(m_dstTypePage, i18n("Select Destination Database Type"));
}
예제 #4
0
//! Constructor (needed for trading interface)
MySQLMigrate::MySQLMigrate(QObject *parent, const char *name,
                           const QStringList &args) :
	KexiMigrate(parent, name, args)
	,d(new MySqlConnectionInternal(0))
	,m_mysqlres(0)
{
	KexiDB::DriverManager manager;
	m_kexiDBDriver = manager.driver("mysql");
}
예제 #5
0
PqxxMigrate::PqxxMigrate(QObject *parent, const QVariantList& args)
        : KexiMigrate(parent, args)
{
    m_res = 0;
    m_trans = 0;
    m_conn = 0;
    m_rows = 0;
    m_row = 0;
    
    KexiDB::DriverManager manager;
    setDriver(manager.driver("pqxx"));
}
예제 #6
0
bool SQLiteAdminTools::vacuum(const KexiDB::ConnectionData& data, const QString& databaseName)
{
    clearError();
    KexiDB::DriverManager manager;
    KexiDB::Driver *drv = manager.driver(data.driverName);
    QString title(i18n("Could not compact database \"%1\".", QDir::toNativeSeparators(databaseName)));
    if (!drv) {
        setError(&manager, title);
        return false;
    }
    SQLiteVacuum vacuum(data.dbPath() + QDir::separator() + databaseName);
    tristate result = vacuum.run();
    if (!result) {
        setError(title);
        return false;
    } else //success or cancelled
        return true;
}
예제 #7
0
xBaseDriver::xBaseDriver( QObject *parent, const QVariantList &args )
  : Driver( parent, args )
  ,dp( new xBaseDriverPrivate() )
{
  KexiDB::DriverManager manager;
  dp->internalDriver = manager.driver(KexiDB::defaultFileBasedDriverName());

  d->isFileDriver = true ;
  d->isDBOpenedAfterCreate = true;
  d->features = SingleTransactions | CursorForward;

  // Everything below is for the SQLite (default file based) driver

  //special method for autoincrement definition
  beh->SPECIAL_AUTO_INCREMENT_DEF = true;
  beh->AUTO_INCREMENT_FIELD_OPTION = ""; //not available
  beh->AUTO_INCREMENT_TYPE = "INTEGER";
  beh->AUTO_INCREMENT_PK_FIELD_OPTION = "PRIMARY KEY";
  beh->AUTO_INCREMENT_REQUIRES_PK = true;
  beh->ROW_ID_FIELD_NAME = "OID";

  beh->QUOTATION_MARKS_FOR_IDENTIFIER='"';
  beh->SELECT_1_SUBQUERY_SUPPORTED = true;

  // As we provide a wrapper over SQLite, this aspect will be hidden by SQLite to us.
  beh->_1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY=false;

  initDriverSpecificKeywords(keywords);

  // Ditto like SQLite , as it won't matter
  d->typeNames[Field::Byte]="Byte";
  d->typeNames[Field::ShortInteger]="ShortInteger";
  d->typeNames[Field::Integer]="Integer";
  d->typeNames[Field::BigInteger]="BigInteger";
  d->typeNames[Field::Boolean]="Boolean";
  d->typeNames[Field::Date]="Date";
  d->typeNames[Field::DateTime]="DateTime";
  d->typeNames[Field::Time]="Time";
  d->typeNames[Field::Float]="Float";
  d->typeNames[Field::Double]="Double";
  d->typeNames[Field::Text]="Text";
  d->typeNames[Field::LongText]="CLOB";
  d->typeNames[Field::BLOB]="BLOB";
}
QVariant KexiRecentProjectsModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }
    KexiProjectData *pdata = static_cast<KexiProjectData*>(index.internalPointer());
    bool fileBased = !pdata->constConnectionData()->dbFileName().isEmpty();
    QString opened(openedString(pdata->lastOpened()));
    if (!opened.isEmpty())
        opened.prepend('\n');
    switch (role) {
    case Qt::DisplayRole: {
        //! @todo add support for imported entries, e.g. MS Access
        if (fileBased) {
            QString n = pdata->caption().trimmed();
            if (n.isEmpty())
                n = pdata->constConnectionData()->dbFileName();
            return n
                   + opened;
        }
        else {
            QString n = pdata->captionOrName();
            if (!n.isEmpty()) {
                n += '\n';
            }
            QString serverInfo = pdata->connectionData()->serverInfoString(false /* without user */);
            // friendly message:
            if (serverInfo == "localhost") {
                serverInfo = i18n("on local server");
            }
            else {
                serverInfo = i18n("on \"%1\" server", serverInfo);
            }
            return n + serverInfo + opened;
        }
    }
    case Qt::ToolTipRole:
        //! @todo add support for imported entries, e.g. MS Access
        if (fileBased) {
            return i18nc("File database <file>", "File database %1",
                         pdata->constConnectionData()->fileName());
        }
        else {
            KexiDB::DriverManager manager;
            return i18nc("<type> database", "%1 database",
                  manager.driverInfo(pdata->constConnectionData()->driverName).caption);
            return pdata->objectName();
        }
    case Qt::DecorationRole: {
        //! @todo show icon specific to given database or mimetype
        if (fileBased) {
            return KIcon(KexiDB::defaultFileBasedDriverIconName());
        }
        else {
            return KIcon(KEXI_DATABASE_SERVER_ICON_NAME);
        }
    }
    /*case KCategorizedSortFilterProxyModel::CategorySortRole: {
        int index = m_categoryNameIndex.value(info->category);
        if (index >= 0 && index < m_templateCategories.count()) {
            QVariantList list;
            list << index << info->caption; 
            return list;
        }
        return QVariantList();
    }
    case KCategorizedSortFilterProxyModel::CategoryDisplayRole: {
        int index = m_categoryNameIndex.value(info->category);
        if (index >= 0 && index < m_templateCategories.count()) {
            KexiTemplateCategoryInfo category = m_templateCategories.value(index);
            return category.caption;
        }
        return QVariant();
    }*/
    case NameRole:
        return pdata->databaseName();
    /*case CategoryRole:
        return info->category;*/
    default:
        break;
    }
    return QVariant();
}
예제 #9
0
KexiMigrate* ImportWizard::prepareImport(Kexi::ObjectStatus& result)
{
	KexiUtils::WaitCursor wait;
	
	// Start with a driver manager
	KexiDB::DriverManager manager;

	kdDebug() << "Creating destination driver..." << endl;

	// Get a driver to the destination database
	KexiDB::Driver *destDriver = manager.driver(
		m_dstConn->selectedConnectionData() ? m_dstConn->selectedConnectionData()->driverName //server based
		 : KexiDB::Driver::defaultFileBasedDriverName()
		// : m_dstTypeCombo->currentText() //file based
	);
	if (!destDriver || manager.error())
	{
		result.setStatus(&manager);
		kdDebug() << "Manager error..." << endl;
		manager.debugError();
//		result.setStatus(&manager);
	}

	// Set up destination connection data
	KexiDB::ConnectionData *cdata;
	bool cdataOwned = false;
	QString dbname;
	if (!result.error())
	{
		if (m_dstConn->selectedConnectionData())
		{
			//server-based project
			kdDebug() << "Server destination..." << endl;
			cdata = m_dstConn->selectedConnectionData();
			dbname = m_dstNewDBNameLineEdit->text();
		}
		else // if (m_dstTypeCombo->currentText().lower() == KexiDB::Driver::defaultFileBasedDriverName()) 
		{
			//file-based project
			kdDebug() << "File Destination..." << endl;
			cdata = new KexiDB::ConnectionData();
			cdataOwned = true;
			cdata->caption = m_dstNewDBNameLineEdit->text();
			cdata->driverName = KexiDB::Driver::defaultFileBasedDriverName();
			dbname = m_dstConn->selectedFileName();
			cdata->setFileName( dbname );
			kdDebug() << "Current file name: " << dbname << endl;
		}
/*		else
		{
			//TODO This needs a better message
			//KMessageBox::error(this, 
			result.setStatus(i18n("No connection data is available. You did not select a destination filename."),"");
			//return false;
		} */
	}

	// Find a source (migration) driver name
	QString sourceDriverName;
	if (!result.error())
	{
		sourceDriverName = driverNameForSelectedSource();
		if (sourceDriverName.isEmpty())
			result.setStatus(i18n("No appropriate migration driver found."), 
				m_migrateManager.possibleProblemsInfoMsg());
	}

	// Get a source (migration) driver
	KexiMigrate* sourceDriver = 0;
	if (!result.error())
	{
		sourceDriver = m_migrateManager.driver( sourceDriverName );
		if(!sourceDriver || m_migrateManager.error()) {
			kdDebug() << "Import migrate driver error..." << endl;
			result.setStatus(&m_migrateManager);
		}
	}

	KexiUtils::removeWaitCursor();

	// Set up source (migration) data required for connection
	if (sourceDriver && !result.error())
	{
		// Setup progress feedback for the GUI
		if(sourceDriver->progressSupported()) {
			m_progressBar->updateGeometry();
			disconnect(sourceDriver, SIGNAL(progressPercent(int)), 
				this, SLOT(progressUpdated(int)));
			connect(sourceDriver, SIGNAL(progressPercent(int)),
				this, SLOT(progressUpdated(int)));
			progressUpdated(0);
		}

		bool keepData;
		if (m_importTypeButtonGroup->selectedId() == 0)
		{
			kdDebug() << "Structure and data selected" << endl;
			keepData = true;
		}
		else if (m_importTypeButtonGroup->selectedId() == 1)
		{
			kdDebug() << "structure only selected" << endl;
			keepData = false;
		}
		else
		{
			kdDebug() << "Neither radio button is selected (not possible?) presume keep data" << endl;
			keepData = true;
		}
		
		KexiMigration::Data* md = new KexiMigration::Data();
	//	delete md->destination;
		md->destination = new KexiProjectData(*cdata, dbname);
		if(fileBasedSrcSelected()) {
			KexiDB::ConnectionData* conn_data = new KexiDB::ConnectionData();
			conn_data->setFileName(m_srcConn->selectedFileName());
			md->source = conn_data;
			md->sourceName = "";
		}
		else 
		{
			if (m_predefinedConnectionData)
				md->source = m_predefinedConnectionData;
			else
				md->source = m_srcConn->selectedConnectionData();

			if (!m_predefinedDatabaseName.isEmpty())
				md->sourceName = m_predefinedDatabaseName;
			else
				md->sourceName = m_srcDBName->selectedProjectData()->databaseName();
	//! @todo Aah, this is so C-like. Move to performImport().
		}
		md->keepData = keepData;
		sourceDriver->setData(md);
		return sourceDriver;
	}
예제 #10
0
//=============================================================================
// Perform Import operation
bool KexiMigrate::performImport(Kexi::ObjectStatus* result)
{
    if (result)
        result->clearStatus();

    KexiDB::DriverManager drvManager;
    KexiDB::Driver *destDriver = drvManager.driver(
                                     m_migrateData->destination->connectionData()->driverName);
    if (!destDriver) {
        result->setStatus(&drvManager,
                          i18n("Could not create database \"%1\".",
                               m_migrateData->destination->databaseName()));
        return false;
    }

    QStringList tables;

    // Step 1 - connect
    kDebug() << "KexiMigrate::performImport() CONNECTING...";
    if (!drv_connect()) {
        kDebug() << "Couldnt connect to database server";
        if (result)
            result->setStatus(i18n("Could not connect to data source \"%1\".",
                                   m_migrateData->source->serverInfoString()), "");
        return false;
    }

    // Step 2 - get table names
    kDebug() << "KexiMigrate::performImport() GETTING TABLENAMES...";
    if (!tableNames(tables)) {
        kDebug() << "Couldnt get list of tables";
        if (result)
            result->setStatus(
                i18n("Could not get a list of table names for data source \"%1\".",
                     m_migrateData->source->serverInfoString()), "");
        return false;
    }

    // Check if there are any tables
    if (tables.isEmpty()) {
        kDebug() << "There were no tables to import";
        if (result)
            result->setStatus(
                i18n("No tables to import found in data source \"%1\".",
                     m_migrateData->source->serverInfoString()), "");
        return false;
    }

    // Step 3 - Read table schemas
    tables.sort();
    m_tableSchemas.clear();
    if (!destDriver) {
        result->setStatus(&drvManager);
        return false;
    }
    const bool kexi__objects_exists = tables.contains("kexi__objects");
    QStringList kexiDBTables;
    if (kexi__objects_exists) {
        tristate res = drv_queryStringListFromSQL(
                           QString::fromLatin1("SELECT o_name FROM kexi__objects WHERE o_type=%1")
                           .arg((int)KexiDB::TableObjectType), 0, kexiDBTables, -1);
        if (res == true) {
            // prepend KexiDB-compatible tables to 'tables' list, so we'll copy KexiDB-compatible tables first,
            // to make sure existing IDs will not be in conflict with IDs newly generated for non-KexiDB tables
            kexiDBTables.sort();
            foreach(const QString& tableName, kexiDBTables)
            tables.removeAt(tables.indexOf(tableName));
//kDebug() << "KexiDB-compat tables: " << kexiDBTables;
//kDebug() << "non-KexiDB tables: " << tables;
        }
    }
예제 #11
0
int main(int argc, char** argv)
{
    Q_UNUSED(argv);
    Q_UNUSED(argc);
    // first the formalities
    QByteArray prgname;

    //! TODO use KCmdLineArguments with options
    // first argument should be xbase source directory
    QString xBaseSourceDirectory = QString::fromLatin1(argv[1]);

    // second argument should be kexi file ( destination )
    QString destinationDatabase = QString::fromLatin1(argv[2]);

    QFileInfo info = QFileInfo(argv[0]);
    prgname = info.baseName().toLatin1();

    //Needed for variosu things like i18n and kconfig and stuff. No need to keep it around or clean it as this is just a test case so nothing long-lived
    new KComponentData(prgname);

    // write the code for testing migration here
    // Start with a driver manager
    KexiDB::DriverManager manager;
    KexiMigration::MigrateManager migrateManager;

    kDebug() << "Creating destination driver...";

    // Get a driver to the destination database
    KexiDB::Driver *destDriver = manager.driver(KexiDB::defaultFileBasedDriverName() //file based
                                               );
    if (!destDriver || manager.error()) {
        kDebug() << "Manager error...";
        manager.debugError();
    }

    KexiDB::ConnectionData *cdata;
    QString dbname;

    cdata = new KexiDB::ConnectionData();

    // set destination file name here.
    //! TODO User should be able to specify this
    cdata->driverName = KexiDB::defaultFileBasedDriverName();

    //! TODO User should be able to specify this
    dbname = destinationDatabase;
    cdata->setFileName(dbname);
    kDebug() << "Current file name: " << dbname;


    QString sourceDriverName = "xbase";
    // get the source migration driver
    KexiMigration::KexiMigrate* sourceDriver = 0;
    sourceDriver = migrateManager.driver(sourceDriverName);
    if (!sourceDriver || migrateManager.error()) {
        kDebug() << "Import migrate driver error...";
        return -1;
    }

    KexiMigration::Data* md = new KexiMigration::Data();
    md->keepData = true;
    // delete md->destination;
    md->destination = new KexiProjectData(*cdata, dbname);

    // Setup XBase connection data
    KexiDB::ConnectionData* conn_data = new KexiDB::ConnectionData();
    conn_data->setFileName(xBaseSourceDirectory);

    md->source = conn_data;
    md->sourceName = "";

    sourceDriver->setData(md);

    if (!sourceDriver->performImport()) {
        kDebug() << "Import failed";
        return -1;
    }

    return 0;
}
예제 #12
0
int main(int argc, char * argv[])
{
    KComponentData componentData("newapi");
    KexiDB::DriverManager manager;
    QStringList names = manager.driverNames();
    kDebug() << "DRIVERS: ";
    for (QStringList::ConstIterator it = names.constBegin(); it != names.constEnd() ; ++it)
        kDebug() << *it;
    if (manager.error()) {
        kDebug() << manager.errorMsg();
        return 1;
    }

    //get driver
    KexiDB::Driver *driver = manager.driver("mySQL");
    if (manager.error()) {
        kDebug() << manager.errorMsg();
        return 1;
    }

    //connection data that can be later reused
    KexiDB::ConnectionData conn_data;

    conn_data.userName = "******";
    if (argc > 1)
        conn_data.password = argv[1];
    else
        conn_data.password = "******";
    conn_data.hostName = "localhost";

    KexiDB::Connection *conn = driver->createConnection(conn_data);
    if (driver->error()) {
        kDebug() << driver->errorMsg();
        return 1;
    }
    if (!conn->connect()) {
        kDebug() << conn->errorMsg();
        return 1;
    }
    if (!conn->useDatabase("test")) {
        kDebug() << "use db:" << conn->errorMsg();
        return 1;
    }

    kDebug() << "Creating first cursor";
    KexiDB::Cursor *c = conn->executeQuery("select * from Applications");
    if (!c) kDebug() << conn->errorMsg();
    kDebug() << "Creating second cursor";
    KexiDB::Cursor *c2 = conn->executeQuery("select * from Applications");
    if (!c2) kDebug() << conn->errorMsg();

    QStringList l = conn->databaseNames();
    if (l.isEmpty()) kDebug() << conn->errorMsg();
    kDebug() << "Databases:";
    for (QStringList::ConstIterator it = l.constBegin(); it != l.constEnd() ; ++it)
        kDebug() << *it;

    if (c) {
        while (c->moveNext()) {
            kDebug() << "Cursor: Value(0)" << c->value(0).toString();
            kDebug() << "Cursor: Value(1)" << c->value(1).toString();
        }
        kDebug() << "Cursor error:" << c->errorMsg();
    }
    if (c2) {
        while (c2->moveNext()) {
            kDebug() << "Cursor2: Value(0)" << c2->value(0).toString();
            kDebug() << "Cursor2: Value(1)" << c2->value(1).toString();
        }
    }
    if (c) {
        kDebug() << "Cursor::prev";
        while (c->movePrev()) {
            kDebug() << "Cursor: Value(0)" << c->value(0).toString();
            kDebug() << "Cursor: Value(1)" << c->value(1).toString();

        }
        kDebug() << "up/down";
        c->moveNext();
        kDebug() << "Cursor: Value(0)" << c->value(0).toString();
        kDebug() << "Cursor: Value(1)" << c->value(1).toString();
        c->moveNext();
        kDebug() << "Cursor: Value(0)" << c->value(0).toString();
        kDebug() << "Cursor: Value(1)" << c->value(1).toString();
        c->movePrev();
        kDebug() << "Cursor: Value(0)" << c->value(0).toString();
        kDebug() << "Cursor: Value(1)" << c->value(1).toString();
        c->movePrev();
        kDebug() << "Cursor: Value(0)" << c->value(0).toString();
        kDebug() << "Cursor: Value(1)" << c->value(1).toString();

    }
#if 0
    KexiDB::Table *t = conn->tableSchema("persons");
    if (t)
        t->debug();
    t = conn->tableSchema("cars");
    if (t)
        t->debug();

// conn->tableNames();

    if (!conn->disconnect()) {
        kDebug() << conn->errorMsg();
        return 1;
    }
    debug("before del");
    delete conn;
    debug("after del");
#endif
    return 0;
}
예제 #13
0
//! Constructor (needed for trading interface)
xBaseMigrate::xBaseMigrate(QObject *parent, const QVariantList& args) :
  KexiMigrate(parent, args)
{
  KexiDB::DriverManager manager;
  setDriver(manager.driver("xbase"));
}
예제 #14
0
int main(int argc, char** argv)
{
    int minargs = 2;
    bool gui = false;
    /* if (argc < minargs) {
        usage();
        RETURN(0);
      }*/
    QFileInfo info = QFileInfo(argv[0]);
    prgname = info.baseName().toLatin1();

    KAboutData aboutData(prgname, 0, ki18n("KexiDBTest"),
                         KEXI_VERSION_STRING, KLocalizedString(), KAboutData::License_GPL,
                         ki18n("(c) 2003-2010, Kexi Team\n"
                               "(c) 2003-2006, OpenOffice Software.\n"),
                         KLocalizedString(),
                         "http://www.calligra.org/kexi",
                         "*****@*****.**");
    KCmdLineArgs::init(argc, argv, &aboutData);

    KCmdLineOptions options;
    options.add("test <test_name>", ki18n("Available tests:\n"
                                          "- cursors: test for cursors behaviour\n"
                                          "- schema: test for db schema retrieving\n"
                                          "- dbcreation: test for new db creation\n"
                                          "- tables: test for tables creation and data\n"
                                          "   inserting\n"
#ifndef NO_GUI
                                          "- tableview: test for KexiDataTableView data-aware\n"
                                          "   widget\n"
#endif
                                          "- parser: test for parsing sql statements,\n"
                                          "   returns debug string for a given\n"
                                          "   sql statement or error message\n"
                                          "- dr_prop: shows properties of selected driver"));
    options.add("buffered-cursors", ki18n("Optional switch: turns cursors used in any tests\n"
                                          " to be buffered"));
    options.add("query-params <params>", ki18n("Query parameters separated\n"
                "by '|' character that will be passed to query\n"
                "statement to replace [...] placeholders."));
    options.add("", ki18n(" Notes:\n"
                          "1. 'dr_prop' requires <db_name> argument.\n"
                          "2. 'parser' test requires <db_name>,\n"
                          " <driver_name> and <sql_statement> arguments\n"
                          "3. All other tests require <db_name>\n"
                          " and <driver_name> arguments.\n"
                          "4. 'tables' test automatically runs 'dbcreation'\n"
                          " test. (<new_db_name> is removed if already exists).\n"
                          "5. <db_name> must be a valid kexi database\n"
                          " e.g. created with 'tables' test."));
    options.add("+driver_name", ki18n("Driver name"));
    options.add("+[db_name]", ki18n("Database name"));
    options.add("+[sql_statement]", ki18n("Optional SQL statement (for parser test)"));
    KCmdLineArgs::addCmdLineOptions(options);

    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    QStringList tests;
    tests << "cursors" << "schema" << "dbcreation" << "tables"
    << "tableview" << "parser" << "dr_prop";
    if (!args->isSet("test")) {
        kDebug() << "No test specified. Use --help.";
        RETURN(1);
    }
    test_name = args->getOption("test");
    if (!tests.contains(test_name)) {
        kDebug() << QString("No such test \"%1\". Use --help.").arg(test_name);
        RETURN(1);
    }

    if (test_name == "tableview") {
        gui = true;
    } else if (test_name == "parser") {
        minargs = 3;
    } else if (test_name == "dr_prop") {
        minargs = 1;
        db_name_required = false;
    }
    if ((int)args->count() < minargs) {
        kDebug() << QString("Not enough args (%1 required). Use --help.").arg(minargs);
        RETURN(1);
    }

    if (gui) {
        app = new QApplication(true);
        app->setWindowIcon(koIcon("table"));
        instance = new KComponentData(KGlobal::mainComponent());
        KIconLoader::global()->addAppDir("kexi");
    } else {
        instance = new KComponentData(prgname);
    }

    drv_name = args->arg(0);

    KexiDB::DriverManager manager;
    QStringList names = manager.driverNames();
    kDebug() << "DRIVERS: ";
    for (QStringList::ConstIterator it = names.constBegin(); it != names.constEnd() ; ++it)
        kDebug() << *it;
    if (manager.error() || names.isEmpty()) {
        manager.debugError();
        RETURN(1);
    }

    //get driver
    const KexiDB::Driver::Info drv_info = manager.driverInfo(drv_name);
    driver = manager.driver(drv_name);
    if (drv_info.name.isEmpty() || manager.error()) {
        manager.debugError();
        RETURN(1);
    }
    kDebug() << "MIME type for '" << drv_info.name << "': " << drv_info.fileDBMimeType;

    //open connection
    if (args->count() >= 2)
        db_name = args->arg(1);

    if (db_name_required && db_name.isEmpty()) {
        kDebug() << prgname << ": database name?";
        RETURN(1);
    }
    if (!db_name.isEmpty()) {
        //additional switches:
        if (args->isSet("buffered-cursors")) {
            cursor_options |= KexiDB::Cursor::Buffered;
        }
        KexiProjectData project_data;
        project_data.setDatabaseName(db_name);
        if (drv_info.fileBased) {
            project_data.connectionData()->setFileName(db_name);
        }
        project_data.connectionData()->driverName = drv_name;
        project = new KexiProject(project_data);
        bool incompatibleWithKexi = false;
        tristate res;
        if (test_name == "dbcreation" || test_name == "tables")
            res = project->create(true /*force overwrite*/);
        else
            res = project->open(incompatibleWithKexi);
        if (res != true) {
            if (incompatibleWithKexi)
                kDebug() << "incompatibleWithKexi";
            project->debugError();
            RETURN(1);
        }
        conn = project->dbConnection();
/*        conn = driver->createConnection(conn_data);
        if (!conn || driver->error()) {
            driver->debugError();
            RETURN(1);
        }
        if (!conn->connect()) {
            conn->debugError();
            RETURN(1);
        }*/
    }

    //start test:
    int r = 0;
    if (test_name == "cursors")
        r = cursorsTest();
    else if (test_name == "schema")
        r = schemaTest();
    else if (test_name == "dbcreation")
        r = dbCreationTest();
    else if (test_name == "tables")
        r = tablesTest();
#ifndef NO_GUI
    else if (test_name == "tableview")
        r = tableViewTest();
#endif
    else if (test_name == "parser") {
        QStringList params;
        if (args->isSet("query-params"))
            params = args->getOption("query-params").split('|');
        r = parserTest(QString(args->arg(2)), params);
    } else if (test_name == "dr_prop")
        r = drPropTest();
    else {
        kWarning() << "No such test: " << test_name;
//  usage();
        RETURN(1);
    }

    if (app && r == 0)
        app->exec();

    if (r)
        kDebug() << "RECENT SQL STATEMENT: " << conn->recentSQLString();

    if (project) {
        if (!project->closeConnection())
            r = 1;
        delete project;
    }
//    if (conn && !conn->disconnect())
//        r = 1;

// kDebug() << "!!! KexiDB::Transaction::globalcount == " << KexiDB::Transaction::globalCount();
// kDebug() << "!!! KexiDB::TransactionData::globalcount == " << KexiDB::TransactionData::globalCount();

    delete app;

    RETURN(r);
}