Bug 262658 - there is no schema selector in the database import wizard
Summary: there is no schema selector in the database import wizard
Status: CLOSED FIXED
Alias: None
Product: KEXI
Classification: Applications
Component: Migration/Import/Export (show other bugs)
Version: unspecified
Platform: Compiled Sources Linux
: NOR wishlist
Target Milestone: ---
Assignee: Adam Pigg
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-01-09 14:12 UTC by Zsombor
Modified: 2012-08-11 11:48 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
implementation (11.99 KB, patch)
2011-01-09 14:12 UTC, Zsombor
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Zsombor 2011-01-09 14:12:42 UTC
Created attachment 55766 [details]
implementation

Version:           unspecified (using KDE 4.5.5) 
OS:                Linux

In the database import wizard, there is no way to specify which schema to select, so it is impossible to select a table - because the wizard unable to read the name of the tables without a schema, if a mysql connection is specified.

Reproducible: Always
Comment 1 Jarosław Staniek 2011-01-10 00:00:21 UTC
Hi Zsombor,
Perhaps there is a problem with connecting to locally run server. Does the "Test Connection" button show success?
If that's not the case, you can Edit the connection settings (Edit Database Connection dialog) and click on second "Details" tab. Then unselect "Default" checkbox for socket file and enter proper local socket file you use for MySQL.

You can find out by executing from command line: "ps a | grep mysql" and locating --socket=... part.
My system (opensuse 11.3) returns --socket=/var/run/mysql/mysql.sock

Kexi tries to find the socket path, but it can fail. 
So far it tries /var/lib/mysql/mysql.sock, /var/run/mysqld/mysqld.sock, /tmp/mysql.sock. Kexi 2.3.1 and newer will also try /var/run/mysql/mysql.sock path.

You can also post your own path, if it's different, so we include it.
Comment 2 Zsombor 2011-01-10 00:19:33 UTC
Sorry, I don't understand, how this connectivity issue is related to the schema selector. The problem is, that in "MySQLMigrate::drv_connect()" there is a call to " return d->useDatabase(m_migrateData->sourceName);" where the 'sourceName' is empty. And that is empty, because in the connection editor dialog, there is no way to specify the name of the schema - only the machine name/port/username/password, and 'title' can be configured. I don't think it's a problem alone - but in the import wizard it's a blocker.
 I've attached a patch, which solves this issue - adding a separate, schema selector to the wizard, please look into.

Thanks
Comment 3 Zsombor 2011-01-10 00:34:38 UTC
Sorry, probably I wrongly specified the problem, the problem is in the 'Import tables' functionality, not in the 'Import database' function.
Comment 4 Jarosław Staniek 2011-01-16 23:51:08 UTC
Adam, could you look at this?
Comment 5 Adam Pigg 2011-01-17 08:42:20 UTC
The import table functionality isnt implemented for the mysql driver, there is a whole bunch of virtual functions to implement.  I'll try and have a go.  Does the patch actually work to import a table as it doesnt implement any of the functions?
Comment 6 Zsombor 2011-01-17 09:22:24 UTC
No, this patch only implements the schema selector functionality, so the user can select one table, after a schema is specified
Comment 7 Adam Pigg 2011-01-17 23:50:47 UTC
commit 0cc3c815555e9385884b08e6de36ff08792f964f
branch master
Author: Adam Pigg <adam@piggz.co.uk>
Date:   Mon Jan 17 19:38:41 2011 +0000

    Memleak fixes
    Show a database select page after the connection page
    (Blank for file based source atm)
    Fixes part of
    BUG:262658

diff --git a/kexi/migration/AlterSchemaWidget.cpp b/kexi/migration/AlterSchemaWidget.cpp
index e7b510d..07fa8b1 100644
--- a/kexi/migration/AlterSchemaWidget.cpp
+++ b/kexi/migration/AlterSchemaWidget.cpp
@@ -69,6 +69,7 @@ AlterSchemaWidget::AlterSchemaWidget(QWidget *parent) : QWidget(parent)
 
 AlterSchemaWidget::~AlterSchemaWidget()
 {
+    delete m_model;
 
 }
 
diff --git a/kexi/migration/importtablewizard.cpp b/kexi/migration/importtablewizard.cpp
index c446d97..a652b30 100644
--- a/kexi/migration/importtablewizard.cpp
+++ b/kexi/migration/importtablewizard.cpp
@@ -50,6 +50,7 @@
 #include <kexipart.h>
 #include <KexiMainWindowIface.h>
 #include <kexiproject.h>
+#include <widget/kexiprjtypeselector.h>
 
 using namespace KexiMigration;
 
@@ -58,11 +59,13 @@ using namespace KexiMigration;
 ImportTableWizard::ImportTableWizard ( KexiDB::Connection* curDB, QWidget* parent, Qt::WFlags flags ) : KAssistantDialog ( parent, flags ) {
     m_currentDatabase = curDB;
     m_migrateDriver = 0;
+    m_prjSet = 0;
     m_migrateManager = new MigrateManager();
     m_importComplete = false;
     
     setupIntroPage();
     setupSrcConn();
+    setupSrcDB();
     setupTableSelectPage();
     setupAlterTablePage();
     setupImportingPage();
@@ -75,6 +78,9 @@ ImportTableWizard::ImportTableWizard ( KexiDB::Connection* curDB, QWidget* paren
 
 ImportTableWizard::~ImportTableWizard() {
   delete m_migrateManager;
+  delete m_prjSet;
+  delete m_srcConnSel;
+  
 }
 
 void ImportTableWizard::back() {
@@ -157,6 +163,17 @@ void ImportTableWizard::setupSrcConn()
     addPage(m_srcConnPageItem);
 }
 
+void ImportTableWizard::setupSrcDB()
+{
+    // arrivesrcdbPage creates widgets on that page
+    m_srcDBPageWidget = new QWidget(this);
+    m_srcDBName = NULL;
+    
+    m_srcDBPageItem = new KPageWidgetItem(m_srcDBPageWidget, i18n("Select Source Database"));
+    addPage(m_srcDBPageItem);
+}
+
+
 void ImportTableWizard::setupTableSelectPage() {
     m_tablesPageWidget = new QWidget(this);
     QVBoxLayout *vbox = new QVBoxLayout(m_tablesPageWidget);
@@ -253,6 +270,8 @@ void ImportTableWizard::slot_currentPageChanged(KPageWidgetItem* curPage,KPageWi
     }
     else if (curPage == m_srcConnPageItem) {
         arriveSrcConnPage();
+    } else if (curPage == m_srcDBPageItem) {
+        arriveSrcDBPage();
     } else if (curPage == m_tablesPageItem) {
         arriveTableSelectPage();
     } else if (curPage == m_alterTablePageItem) {
@@ -269,6 +288,28 @@ void ImportTableWizard::arriveSrcConnPage()
     kDebug();
 }
 
+void ImportTableWizard::arriveSrcDBPage()
+{
+    if (fileBasedSrcSelected()) {
+        //! @todo Back button doesn't work after selecting a file to import
+        //moved showPage(m_dstTypePage);
+    } else if (!m_srcDBName) {
+        m_srcDBPageWidget->hide();
+        kDebug() << "Looks like we need a project selector widget!";
+        
+        KexiDB::ConnectionData* condata = m_srcConnSel->selectedConnectionData();
+        if (condata) {
+            m_prjSet = new KexiProjectSet(*condata);
+            QVBoxLayout *vbox = new QVBoxLayout(m_srcDBPageWidget);
+            KexiUtils::setStandardMarginsAndSpacing(vbox);
+            m_srcDBName = new KexiProjectSelectorWidget(m_srcDBPageWidget, m_prjSet);
+            vbox->addWidget(m_srcDBName);
+            m_srcDBName->label()->setText(i18n("Select source database you wish to import:"));
+        }
+        m_srcDBPageWidget->show();
+    }
+}
+
 void ImportTableWizard::arriveTableSelectPage()
 {
     Kexi::ObjectStatus result;
@@ -452,9 +493,10 @@ KexiMigrate* ImportTableWizard::prepareImport(Kexi::ObjectStatus& result)
             md->sourceName.clear();
         } else {
             md->source = m_srcConnSel->selectedConnectionData();
-            //md->sourceName = m_srcDBName->selectedProjectData()->databaseName();
+            md->sourceName = m_srcDBName->selectedProjectData()->databaseName();
             
         }
+        
         md->keepData = keepData;
         sourceDriver->setData(md);
         
diff --git a/kexi/migration/importtablewizard.h b/kexi/migration/importtablewizard.h
index e871ee1..14270b5 100644
--- a/kexi/migration/importtablewizard.h
+++ b/kexi/migration/importtablewizard.h
@@ -27,6 +27,8 @@ class KexiConnSelectorWidget;
 class QListWidget;
 class QLabel;
 class QProgressBar;
+class KexiProjectSelectorWidget;
+class KexiProjectSet;
 
 namespace KexiDB {
     class Connection;
@@ -66,7 +68,8 @@ Q_OBJECT
         QPointer<KexiMigration::KexiMigrate> m_migrateDriver;
         QListWidget *m_tableListWidget;
         AlterSchemaWidget *m_alterSchemaWidget;
-
+        KexiProjectSelectorWidget *m_srcDBName;
+        KexiProjectSet* m_prjSet;
         QString m_importTableName;
         
         bool fileBasedSrcSelected() const;
@@ -80,14 +83,15 @@ Q_OBJECT
         bool doImport();
         
         //Page Items
-        KPageWidgetItem *m_introPageItem, *m_srcConnPageItem, *m_tablesPageItem, *m_alterTablePageItem, *m_importingPageItem, *m_finishPageItem;
+        KPageWidgetItem *m_introPageItem, *m_srcConnPageItem, *m_srcDBPageItem, *m_tablesPageItem, *m_alterTablePageItem, *m_importingPageItem, *m_finishPageItem;
         
         //Page Widgets
-        QWidget *m_introPageWidget, *m_srcConnPageWidget, *m_tablesPageWidget, *m_alterTablePageWidget, *m_importingPageWidget, *m_finishPageWidget;
+        QWidget *m_introPageWidget, *m_srcConnPageWidget, *m_srcDBPageWidget, *m_tablesPageWidget, *m_alterTablePageWidget, *m_importingPageWidget, *m_finishPageWidget;
 
         //Page Setup
         void setupIntroPage();
         void setupSrcConn();
+        void setupSrcDB();
         void setupTableSelectPage();
         void setupAlterTablePage();
         void setupImportingPage();
@@ -95,6 +99,7 @@ Q_OBJECT
         
         //Page Arrival
         void arriveSrcConnPage();
+        void arriveSrcDBPage();
         void arriveTableSelectPage();
         void arriveAlterTablePage();
         void arriveImportingPage();
Comment 8 Adam Pigg 2011-01-17 23:50:48 UTC
commit 91d640e118c053e1023282f3c21e9f64f45b3234
branch master
Author: Adam Pigg <adam@piggz.co.uk>
Date:   Mon Jan 17 22:45:39 2011 +0000

    Implement support for importing a table
    BUG:262658
    Tested by importing several tables from akonadi using a custom socket.
    Both complex and v large tables worked fine.

diff --git a/kexi/migration/mysql/mysqlmigrate.cpp b/kexi/migration/mysql/mysqlmigrate.cpp
index 4d358ae..431b2b9 100644
--- a/kexi/migration/mysql/mysqlmigrate.cpp
+++ b/kexi/migration/mysql/mysqlmigrate.cpp
@@ -71,6 +71,7 @@ MySQLMigrate::MySQLMigrate(QObject *parent, const QVariantList& args) :
         KexiMigrate(parent, args)
         , d(new MySqlConnectionInternal(0))
         , m_mysqlres(0)
+        , m_dataRow(0)
 {
     KexiDB::DriverManager manager;
     m_kexiDBDriver = manager.driver("mysql");
@@ -80,9 +81,8 @@ MySQLMigrate::MySQLMigrate(QObject *parent, const QVariantList& args) :
 //! Destructor
 MySQLMigrate::~MySQLMigrate()
 {
-    if (m_mysqlres)
-        mysql_free_result(m_mysqlres);
-    m_mysqlres = 0;
+    mysql_free_result(m_mysqlres);
+    delete d;
 }
 
 
@@ -114,6 +114,7 @@ bool MySQLMigrate::drv_readTableSchema(
 // tableSchema.setCaption(table + " table");
 
     //Perform a query on the table to get some data
+    tableSchema.setName(originalName);
     QString query = QString("SELECT * FROM `") + drv_escapeIdentifier(originalName) + "` LIMIT 0";
     if (!d->executeSQL(query))
         return false;
@@ -509,5 +510,103 @@ void MySQLMigrate::getOptions(int flags, KexiDB::Field* fld)
     fld->setUnsigned(flags & UNSIGNED_FLAG);
 }
 
+bool MySQLMigrate::drv_moveFirst()
+{
+    if (!m_mysqlres)
+        return false;
+    
+    m_row = 0;
+    getRow();
+    return true;
+}
+
+bool MySQLMigrate::drv_moveLast()
+{
+    if (!m_mysqlres)
+        return false;
+    
+    m_row = m_rows - 1;
+    getRow();
+    return true;
+}
+
+bool MySQLMigrate::drv_moveNext()
+{
+    if (!m_mysqlres)
+        return false;
+    
+    if (m_row < m_rows - 1) {
+        m_row ++;
+        getRow();
+        return true;
+    }
+    else
+    {
+        return false;
+    }     
+}
+
+bool MySQLMigrate::drv_movePrevious()
+{
+    if (!m_mysqlres)
+        return false;
+    
+    if (m_row > 0) {
+        m_row --;
+        getRow();
+        return true;
+    }
+    else
+    {
+        return false;
+    }  
+}
+
+bool MySQLMigrate::drv_readFromTable(const QString& tableName)
+{
+    kDebug();
+    
+    if (!d->executeSQL("SELECT * FROM `" + drv_escapeIdentifier(tableName) + '`')) {
+        kDebug() << "Unable to execute SQL";
+        return false;
+    }
+    
+    m_mysqlres = mysql_store_result(d->mysql);
+    if(!m_mysqlres) {
+        return false;
+    }
+    
+    m_rows = mysql_num_rows(m_mysqlres);
+    kDebug() << m_rows;
+    
+    return true;
+}
+
+QVariant MySQLMigrate::drv_value(uint i)
+{
+    QString val;
+    if (m_dataRow) {
+        val = m_dataRow[i];
+    }else {
+        kDebug() << "No row";
+    }
+    
+    return val;
+}
+
+void MySQLMigrate::getRow()
+{
+    if (m_mysqlres) {
+        mysql_data_seek(m_mysqlres, m_row);
+        m_dataRow = mysql_fetch_row(m_mysqlres);
+    } else {
+        kDebug() << "No result";
+        m_dataRow = 0;   
+    }
+}
+
+
+
+
 
 #include "mysqlmigrate.moc"
diff --git a/kexi/migration/mysql/mysqlmigrate.h b/kexi/migration/mysql/mysqlmigrate.h
index 508ec67..1b10a76 100644
--- a/kexi/migration/mysql/mysqlmigrate.h
+++ b/kexi/migration/mysql/mysqlmigrate.h
@@ -82,10 +82,35 @@ protected:
 //   virtual bool drv_getTablesList( QStringList &list );
 //TODO: move this somewhere to low level class (MIGRATION?)
 //   virtual bool drv_containsTable( const QString &tableName );
+    
+    //Extended API
+    //! Position the source dataset at the start of a table
+    virtual bool drv_readFromTable(const QString & tableName);
+    
+    //! Move to the next row
+    virtual bool drv_moveNext();
+    
+    //! Move to the previous row
+    virtual bool drv_movePrevious();
+    
+    //! Move to the next row
+    virtual bool drv_moveFirst();
+    
+    //! Move to the previous row
+    virtual bool drv_moveLast();
+    
+    //! Read the data at the given row/field
+    virtual QVariant drv_value(uint i);
 
 private:
     MySqlConnectionInternal * const d;
     MYSQL_RES *m_mysqlres;
+    
+    long m_rows;
+    long m_row;
+    MYSQL_ROW m_dataRow;
+    
+    void getRow();
 };
 }