Russian Qt Forum
Май 19, 2024, 12:18 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 5 6 [7] 8 9 ... 14   Вниз
  Печать  
Автор Тема: Транзакции Interbase  (Прочитано 146218 раз)
sarbash
Гость
« Ответ #90 : Март 24, 2010, 18:19 »

А нужно ли было так всё усложнять? Вот то, что мне ответили ранее:

"std::string sql = "INSERT INTO Main (Name)"
                            " Values(\'? ? ?\') RETURNING ID";
        st->Prepare(sql.c_str());
        st->Execute();
        st->Get(1, DocInf.ID);
        tr->Commit();//Commit (здесь было много вопросительных знаков - у автора проблема с кодировкой) ID

I'm sorry but with English I have a problem"

Насколько я понимаю, достаточно где-то что-то подправить в драйвере, не трогая ibpp, т.к. проблема не с ним, что мне продемонстрировали этим примером, да и сам автор ведь написал понятно - он пользует RETURNING постоянно.
« Последнее редактирование: Март 24, 2010, 18:22 от sarbash » Записан
gigabyte
Гость
« Ответ #91 : Март 24, 2010, 18:23 »

Вот именно где-то что-то а оно бы вилилось в много всякого. а так получилось чуть чуть и везде  Улыбающийся
Ну просто мне так легче было исправить. Ваше желание принимать или нет
Записан
sarbash
Гость
« Ответ #92 : Март 24, 2010, 18:31 »

Ничего не имею против ваших корректировок, не подумайте. Улыбающийся
однако, осмелюсь заметить, что если где-то что-то нужное и правильно подпилить, то это никак не повредит делу и не выльется в что-то трагическое, а как раз наоборот, будет багфикс.
Ладно, простите меня великодушно за пустую демагогию, кто бы подарил мне немного времени покопаться во внутренностях драйвера... Грустный
Записан
gigabyte
Гость
« Ответ #93 : Март 24, 2010, 22:12 »

А нужно ли было так всё усложнять? Вот то, что мне ответили ранее:

"std::string sql = "INSERT INTO Main (Name)"
                            " Values(\'? ? ?\') RETURNING ID";
        st->Prepare(sql.c_str());
        st->Execute();
        st->Get(1, DocInf.ID);
        tr->Commit();//Commit (здесь было много вопросительных знаков - у автора проблема с кодировкой) ID

I'm sorry but with English I have a problem"
Шото мне этот пример не нравится Вы его сами пробовали?
Я шас чутьчуть посидел вместо st->Get(1, DocInf.ID); поставил IsNull - так он true показывает а это как понимаэте не то что надо.
        rp->iSt->Get(1,i);
        qDebug() << i;
выписывает совсем левые данные
Если сделать st->Fetch() тоже не получится так как там по коду throw exception рисуется.
Может случайно примерчик не полный? Или все таки IBPP
Записан
sarbash
Гость
« Ответ #94 : Март 25, 2010, 00:08 »

Как я понял, это неполный примерчик с использованием ibpp. Кстати, там должно быть в запросе что-то типа
"INSERT INTO Main (Name) Values(\'Боря, у которого траблы с кодировками в мыле\') RETURNING ID;"
У товарища вопросы вместо русских символов, как я понял.
Записан
sarbash
Гость
« Ответ #95 : Март 26, 2010, 13:58 »

Шото мне этот пример не нравится Вы его сами пробовали?
Я шас чутьчуть посидел вместо st->Get(1, DocInf.ID); поставил IsNull - так он true показывает а это как понимаэте не то что надо.
        rp->iSt->Get(1,i);
        qDebug() << i;
выписывает совсем левые данные
Если сделать st->Fetch() тоже не получится так как там по коду throw exception рисуется.
Может случайно примерчик не полный? Или все таки IBPP

Из принципа попробовал:
test.cpp
Код:
int main(int argc, char *argv[])
{
    IBPP::Database db1;
    db1 = IBPP::DatabaseFactory("localhost", "D:\\projects\\test\\realtyad.fdb", "sysdba", "masterkey");
    db1->Connect();
    IBPP::Transaction tr1 = IBPP::TransactionFactory(db1,
                            IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
    tr1->Start();
    IBPP::Statement st1 = IBPP::StatementFactory(db1, tr1);
    st1->Execute("insert into R (NAME, PHONE1) values ('John Doe', '58-29-58') returning ID");
    tr1->Commit();

    int test_id;
    st1->Get(1, test_id);
    std::cout << "returned id is " << test_id << std::endl;
    db1->Disconnect();
    return 0;
}

Так вот. Всё работает. ID возвращает исправно, проверял IBExpert-ом возвращаемые значения - не врёт, однако. Что будем делать? В перспективе релиза 3.0 IBPP не думаю, что это будет разумным, трогать IBPP, логичней допилить драйвер для нормальной работы с RETURNING.
« Последнее редактирование: Март 26, 2010, 14:02 от sarbash » Записан
sarbash
Гость
« Ответ #96 : Март 26, 2010, 15:37 »

Итак, результат моих родовых мук.
Прилагаю патч, для того, чтобы можно было брать возвращаемое RETURNING значение из синглтона.
Сразу предупреждаю - реализация сделана согласно доки птицевской, то бишь, RETURNING рассчитан на синглтон и никак иначе.
Пробуйте, проверяйте, тестируйте, ругайте, высказывайте замечания, шлите патчи. Подмигивающий

2gigabyte: это ничего, что реализацию ::isSelect() я просто скопировал из твоего поста? Подмигивающий

2axax: патчил, глядя на qsql_ibase.cpp, почти скопипастил логику. Если всё будет ок - можно закомитить в репозиторий.

Всем удачи и хорошего настроения! Улыбающийся

P.S. Немного патч подправил, почти незаметно.
« Последнее редактирование: Март 26, 2010, 16:03 от sarbash » Записан
gigabyte
Гость
« Ответ #97 : Март 26, 2010, 16:20 »

Итак, результат моих родовых мук.
Прилагаю патч, для того, чтобы можно было брать возвращаемое RETURNING значение из синглтона.
Сразу предупреждаю - реализация сделана согласно доки птицевской, то бишь, RETURNING рассчитан на синглтон и никак иначе.
Пробуйте, проверяйте, тестируйте, ругайте, высказывайте замечания, шлите патчи. Подмигивающий

2gigabyte: это ничего, что реализацию ::isSelect() я просто скопировал из твоего поста? Подмигивающий

2axax: патчил, глядя на qsql_ibase.cpp, почти скопипастил логику. Если всё будет ок - можно закомитить в репозиторий.

Всем удачи и хорошего настроения! Улыбающийся

P.S. Немного патч подправил, почти незаметно.

Вечером попробую. а ты сам его уже пробовал?
Записан
sarbash
Гость
« Ответ #98 : Март 26, 2010, 16:41 »

Вечером попробую. а ты сам его уже пробовал?
Улыбающийся))
Это банально, но мой ответ очень предсказуем: "У меня всё работает." Улыбающийся
Я решил, что не стоит трогать IBPP, и внёс изменения в код драйвера. Я сделал по тому же принципу, как это реализовано в драйвере QIBASE, который в комплекте с SDK идёт. Единственное сомнение у меня по поводу процедур... Если верить написанному:
Код:
bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx)
{
    ISC_STATUS stat = 0;

    // Stored Procedures are special - they populate our d->sqlda when executing,
    // so we don't have to call isc_dsql_fetch
    if (d->queryType == isc_info_sql_stmt_exec_procedure) {
        // the first "fetch" shall succeed, all consecutive ones will fail since
        // we only have one row to fetch for stored procedures
то проблем быть не должно, а как оно на практике будет, тут я не могу ничего сказать...

P.S. Ещё раз перечитал главу о хранимых процедурах из "Мир Interbase" и понял - "всё правильно сделал!"
Так оно и должно работать.
« Последнее редактирование: Март 26, 2010, 21:55 от sarbash » Записан
gigabyte
Гость
« Ответ #99 : Март 26, 2010, 17:25 »

Цитировать
Это банально, но мой ответ очень предсказуем: "У меня всё работает."
У меня не пошло  Грустный
А конкретно дошло зашло в
Код:
        if (rp->iSt->IsNull(i))
        {
            // null value
            QVariant v;
            v.convert(qIBPPTypeName(rp->iSt->ColumnType(i)));
            row[idx] = v;
            continue;
        }
и соответственно выдало пустой вариант в qDebug()
Код:
Value:  QVariant(, )
Проверял следующим образом:
Код:
        QSqlQuery q("INSERT INTO SYS$ACTIONS(ID,CAPTION) VALUES(NULL,'CAPTION') RETURNING ID",db);
        while(q.next())
            qDebug() << "Value: " << q.value(0);
Записан
sarbash
Гость
« Ответ #100 : Март 26, 2010, 17:41 »

А что за база? большая? (намекаю на поделиться для теста)
А поле точно автоинкрементное?
А что за версия ibpp? я использую 2.5.3.1
Firebird точно >=2.1?
« Последнее редактирование: Март 26, 2010, 17:45 от sarbash » Записан
sarbash
Гость
« Ответ #101 : Март 26, 2010, 17:50 »

Предлагаю для верности эксперимента зааттачить тестовую базу, на которой и будем мучить RETURNING. Если у нас обоих не пойдёт - значит явно глюк, а так невозможно выяснить, в чём дело. У меня всё нормально заработало с пропатченным драйвером.
На всякий случай вот нормальные фрагменты, не diff-ом:
Код:
строки 681-697

    bool stat = true;

    if (IBPP::stExecProcedure == rp->iSt->Type())
    {
    if (0 != rowIdx)
    stat = false;
    }
    else
        try
        {
            stat = rp->iSt->Fetch();
        }
        catch (IBPP::Exception& e)
        {
            rp->setError("Could not fetch next item", e, QSqlError::StatementError);
            return false;
        }

строка 410

        iss = (iSt->Type() == IBPP::stSelect || (iSt->Type() == IBPP::stExecProcedure && 0 < iSt->Columns()));
Записан
gigabyte
Гость
« Ответ #102 : Март 26, 2010, 19:02 »

diff у меня сел нормально
аттачу table.sql для генерации таблицы с триггерами
проверрять я буду так:
Код:
        QSqlQuery q("INSERT INTO SYS$ACTIONS(ID,CAPTION) VALUES(NULL,'CAPTION') RETURNING ID",db);
        QSqlQuery q("SELECT ID FROM SYS$ACTIONS",db);
        while(q.next())
            qDebug() << "Value: " << q.value(0);
1.  собсно для проыверки работы
2.  для проверки того не на@бнулось ли что-то
Записан
sarbash
Гость
« Ответ #103 : Март 26, 2010, 21:31 »

"SYS$UIDGENERATOR" - это где брать?

/*******************************************************************************
The next statement causes the following error:

Undefined name.
Dynamic SQL Error.
SQL error code = -204.
Procedure unknown.
SYS$UIDGENERATOR.
*******************************************************************************/
CREATE OR ALTER TRIGGER SYS$ACTIONS_BI FOR SYS$ACTIONS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
    IF ((NEW.ID IS NULL) OR (NEW.ID = 0)) THEN
        EXECUTE PROCEDURE SYS$UIDGENERATOR 'SYS$ACTIONS' RETURNING_VALUES NEW.ID;
END;


З.Ы. Зачем всё так сложно?... у меня ПК генерится обычным триггером перед вставкой обычным генератором с помощью GEN_ID().
« Последнее редактирование: Март 26, 2010, 21:33 от sarbash » Записан
gigabyte
Гость
« Ответ #104 : Март 26, 2010, 21:42 »

sys$uidgenerator
Код:
SET TERM ^ ;

CREATE OR ALTER PROCEDURE SYS$UIDGENERATOR (
    UIDNAME VARCHAR(40))
RETURNS (
    UID BIGINT)
AS
DECLARE VARIABLE TEMPUID BIGINT;
begin
  SELECT VAL FROM SYS$UIDS WHERE ID = :UIDNAME INTO :TEMPUID;
  UPDATE SYS$UIDS SET VAL = :TEMPUID + 1  WHERE ID = :UIDNAME;
  UID = :TEMPUID;
  SUSPEND;
end^

SET TERM ; ^

GRANT SELECT,UPDATE ON SYS$UIDS TO PROCEDURE SYS$UIDGENERATOR;

GRANT EXECUTE ON PROCEDURE SYS$UIDGENERATOR TO SYSDBA;
Таблица SYS$UIDS:
Код:
CREATE TABLE SYS$UIDS (
    ID   VARCHAR(40),
    VAL  BIGINT DEFAULT 0 NOT NULL
);
Записан
Страниц: 1 ... 5 6 [7] 8 9 ... 14   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.048 секунд. Запросов: 19.