Russian Qt Forum

Qt => Базы данных => Тема начата: antoshib от Декабрь 06, 2016, 14:50



Название: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 06, 2016, 14:50
Экспериментирую тут с Embedded MySQL под Qt, в итоге "оно" через пень колоду заработало.

На данном этапе приложение ломается при завершении и при попытке закрыть соединение.

Лепил по вот этому примеру http://dev.mysql.com/doc/refman/5.7/en/libmysqld-example.html (http://dev.mysql.com/doc/refman/5.7/en/libmysqld-example.html),
с адаптацией под использование Qt классов для работы с БД, т.е.:

Код:
MYSQL       *mysql;

// ... тут соединение с БД

    QMYSQLDriver *drv = new QMYSQLDriver(mysql);
    QSqlDatabase mydb = QSqlDatabase::addDatabase( drv, "connection1" );

//... тут простой запрос, отрабатывает как надо

// и приложение ломается

    if (!mysql) return;

    QSqlDatabase::removeDatabase( "connection1" );

    mysql_close(mysql);
    mysql_library_end();


Если не использовать кутишные классы и делать, как в примере по ссылке,
то приложение не ломается, закрытие соединения отрабатывает как надо.


Название: Re: Отключиться от embedded MySQL
Отправлено: Hellraiser от Декабрь 06, 2016, 15:39
ну а документацию (http://doc.qt.io/qt-5/qsqldatabase.html#removeDatabase) хотя-бы почитать?


Название: Re: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 06, 2016, 15:55
ну а документацию (http://doc.qt.io/qt-5/qsqldatabase.html#removeDatabase) хотя-бы почитать?

хотя бы почитал, выход у меня реализован при закрытии виджета, т.е. в отдельной секции.


Название: Re: Отключиться от embedded MySQL
Отправлено: Hellraiser от Декабрь 06, 2016, 16:09
А все здесь должны об этом догадываться по приведенным обрывкам кода?


Название: Re: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 06, 2016, 16:51
Ок, это выяснили, давайте по существу, пожалуйста, какие еще нужно сведения?
Qt 4.5.2 собраны из исходников static под виндой на MS VC++ Express 2010, MySQL 5.5.30 тоже из исходников собрано.


Название: Re: Отключиться от embedded MySQL
Отправлено: Hellraiser от Декабрь 07, 2016, 08:07
Не нужны ни какие сведения - нужен рабочий код или тестовый код, воспроизводящий проблему.
QMYSQLDriver - это просто ошибка или действительно свой самопальный драйвер?
Что за класс MYSQL?
Для начала код надо проверить на соединение с не-embedded сервером.
P.S. Телепаты все в отпуске...


Название: Re: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 07, 2016, 11:38
QMYSQLDriver подключается из qsql_mysql_p.h из исходников плагина драйвера mysql (%QTDIR%\src\sql\drivers\mysql\qsql_mysql_p.h) в соответствии с рекомендациями в доках по QSqlDatabase::addDatabase, только там для PostgreSQL, но есть и инструкция для мускуля. И вот тут один из примеров реализации http://stackoverflow.com/questions/8364157/use-mysql-embedded-with-qt (http://stackoverflow.com/questions/8364157/use-mysql-embedded-with-qt).

Вот то, что у меня:
Код:
#include "mainwindow.h"

#include <QtDebug>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>
#include <QtSql/QSqlDriver>
#include <QtSql/QtSql>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>


#include <my_config.h>
#include <my_global.h>
#include <mysql.h>
#include "../src/sql/drivers/mysql/qsql_mysql.cpp"

MYSQL       *mysql;
MYSQL_RES   *results;
MYSQL_ROW   record;



static char *server_options[]= { "mysql_test", "--defaults-file=my.ini", NULL };
int             num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
static char *server_groups[] = { "client", "mysqld" "mysql", NULL };


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    qDebug() << "Loading embedded, num_elements"<< num_elements << "..";

    int mli = mysql_library_init(num_elements, server_options, server_groups);

    qDebug() << "init code " << mli;

    mysql = mysql_init(NULL);

    mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP,  "client");
    mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);


    if (mysql != mysql_real_connect( mysql, NULL,NULL,NULL, "mysql", 0, NULL, 0 )){
        qDebug() << "Warning! mysql_real_connect faulted!";
        return;
    }

//
//   Этот код отрабатывает без проблем, но без привязок к классам Qt
//
//    mysql_query(mysql, "SELECT * FROM `user`");
//    results = mysql_store_result(mysql);
//
//    while((record = mysql_fetch_row(results))) {
//       qDebug("%s - %s \n", record[0], record[1]);
//    }
//
//    mysql_free_result(results);
//    mysql_close(mysql);
//    mysql_library_end();



    connect(this, SIGNAL(destroyed()), this, SLOT(releaseMysql()));



    QMYSQLDriver *drv = new QMYSQLDriver(mysql);
    QSqlDatabase mydb = QSqlDatabase::addDatabase( drv, "connection1" );

    qDebug() << "Embedded driver added";

    mydb.setDatabaseName("mysql");

    if ( !mydb.isValid() ){
        qDebug() << "\n\tERR!!! Database driver use fails";
        return;
    }

    qDebug() << "\n\tOK... Database driver accepted";

    if ( mydb.isOpen() ){ //Try to opens the database
        qDebug() << "The database is already opened";
    }else{
        qDebug() << "Try to opens the database";
        mydb.open();
    }


    if (mydb.isOpen()){

        QSqlQuery   query;
        QString     queryText = "SELECT * FROM `user`";
        QSqlRecord  r;

        query = mydb.exec( queryText );

        while( query.next() ){
            r = query.record();
            qDebug("%s - %s \n", r.value(0).toString(), r.value(1).toString());
        }

        qDebug() << "The database is accessable";
    }else
        qDebug() << "Error while opening the database";

}

void MainWindow::releaseMysql(){

    if (!mysql) return;

   // После следующей инструкции возникает эксепшн
   //
    QSqlDatabase::removeDatabase( "connection1" );



    mysql_close(mysql);
    mysql_library_end();

    mysql = 0;
}


MainWindow::~MainWindow()
{

}




Файл проекта:
Код:
QT += core gui sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = untitled
TEMPLATE = app

INCLUDEPATH+="C:/mysql/include/"
INCLUDEPATH+=$$[QT_INSTALL_PREFIX]/src/sql/kernel/
INCLUDEPATH+=$$[QT_INSTALL_PREFIX]/include/QtSql/5.4.2/
INCLUDEPATH+=$$[QT_INSTALL_PREFIX]/include/QtCore/5.4.2/QtCore

SOURCES += \
        $$[QT_INSTALL_PREFIX]/src/sql/drivers/mysql/qsql_mysql.cpp\
        main.cpp\
        mainwindow.cpp\


HEADERS  += mainwindow.h

win32:LIBS+="-L C:/mysql/libmysqld/Debug"



Название: Re: Отключиться от embedded MySQL
Отправлено: Hellraiser от Декабрь 07, 2016, 13:35
Там по ссылке есть ответ с куском из исходника Qt.
Рекомендация: сделать как указано в исходнике, т.е. закомментировать дефайн, пересобрать плагин с указанием в командной строке при сборке директивы линковки статической библиотеки (типа LIBS+="-L C:/mysql/libmysqld/Debug -l libmysqld"), выбросить всю мускульную шнягу из проекта и подключаться как
Код
C++ (Qt)
QSqlDatabase mydb = QSqlDatabase::addDatabase( "MYSQL", "connection1" );
Пусть QSqlDatabase сам обращается куда надо.


Название: Re: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 07, 2016, 14:32
А как при подключении libmysqld узнает о существовании папки с данными или хотя бы my.ini? При сборке модуля это нигде не указывается. Дефайн комментировал, либы подключал.
Попробую, вдруг пойдет по дефолтным настройкам.

upd: не, так не прокатывает - не может открыть бд


Название: Re: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 07, 2016, 16:01
Вынес все таки в отдельный блок addDatabase и стало работать без эксепшена, только ругается при отключении.

QSqlDatabasePrivate::removeDatabase: connection 'connection1' is still in use, all queries will cease to work.


Код:
//...
    QSqlDatabase mydb;
{
    QMYSQLDriver *drv = new QMYSQLDriver(mysql);
    //QSqlDatabase
            mydb = QSqlDatabase::addDatabase( drv, "connection1" );

    qDebug() << "Embedded driver added";

    mydb.setDatabaseName("mysql");

    if ( !mydb.isValid() ){
        qDebug() << "\n\tERR!!! Database driver use fails";
        return;
    }

    qDebug() << "\n\tOK... Database driver accepted";

    if ( mydb.isOpen() ){ //Try to opens the database
        qDebug() << "The database is already opened";
    }else{
        qDebug() << "Try to opens the database";
        mydb.open();
    }
}


    if (mydb.isOpen()){

//...
        query.clear();
        releaseMysql();
        mydb.close();

        qDebug() << "The database is accessable";
    }else
        qDebug() << "Error while opening the database";



Название: Re: Отключиться от embedded MySQL
Отправлено: Hellraiser от Декабрь 07, 2016, 16:54
Не надо отключение базы держать вместе с запросом. Лучше переопределить closeEvent у формы и в нем добавить
Код
C++ (Qt)
QSqlDatabase::removeDatabase("connection1");
Но если используются вьюхи с доступом к этой базе, то все-равно будет ругаться.


Название: Re: Отключиться от embedded MySQL
Отправлено: antoshib от Декабрь 07, 2016, 17:17
Понял, спасибо!