Yes, it makes sence. I was wrong as the procedure still depends on the
table, so it's the intented behaviour. But what I still can't understand is
why did it work before? I mean, old tests were using Jaybird's
AutoCommitTransaction which is just a wrapper around Manageable
transaction, so it should give the same results. And my playing around
transactions supports it:

*cleanup...*

*In auto-commit transaction...*
*Successfully created table*
*Successfully created procedure*
*unsuccessful metadata update*
*-cannot delete*
*-COLUMN TEST_BLOB.ID <http://TEST_BLOB.ID>*
*-there are 1 dependencies*
*Successfully dropped procedure*

*cleanup...*

*In manageable transaction...*
*Successfully created table*
*Successfully created procedure*
*Successfully dropped table*
*Successfully dropped procedure*

*cleanup...*

*In wrapped transaction...*
*Successfully created table*
*Successfully created procedure*
*Successfully dropped table*
*unsuccessful metadata update*
*-cannot delete*
*-COLUMN TEST_BLOB.ID <http://TEST_BLOB.ID>*
*-there are 1 dependencies*
*Successfully dropped procedure*

*cleanup...*

Anyway, it looks like the current behaviour is actually the right one. But
it differs from the previous one.

On Sat, May 30, 2015 at 7:09 PM, Dmitry Yemanov <firebi...@yandex.ru> wrote:

> 29.05.2015 17:10, Maxim Smyatkin wrote:
> >
> > - we create a procedure P using a table T.
> > - the P states its interest in the T (while looking for P's
> dependencies);
> > - transaction commits the changes with retaining flag and forgets to say
> > that it isn't interested in the T anymore;
>
> Externally (for API user) it's the same transaction (even if having
> different ID), so it *is* still interested. If you restart some query
> against T in the same transaction, you should not get a "table not
> found" error. This is the idea behind existence locks.
>
>
> Dmitry
>
>
>
> ------------------------------------------------------------------------------
> Firebird-Devel mailing list, web interface at
> https://lists.sourceforge.net/lists/listinfo/firebird-devel
>



-- 
Thank you!
Smyatkin Maxim, Red Soft Corporation.
https://www.linkedin.com/in/smyatkin
#include <ibase.h>
#include <iostream>
#include <cstring>

using namespace std;

const char* db_name = "localhost:fbtest";

isc_db_handle attach();
bool detach(isc_db_handle* db);
bool executeStatement(const char* query, isc_tr_handle* tr, isc_db_handle* db, bool quiet = false);
isc_tr_handle startManageableTransaction(isc_db_handle* db);
isc_tr_handle startAutoCommitTransaction(isc_db_handle* db);
bool commit(isc_tr_handle* tr);
bool checkError(ISC_STATUS* status_vector, bool quiet = false);
void tryManageable();
void tryWrapped();
void tryAutocommit();
void cleanUp();

const char* CREATE_TABLE = "CREATE TABLE test_blob("
                           "  id INTEGER, "
                           "  bin_data BLOB, "
                           "  char_data BLOB SUB_TYPE 1  "
                           ")";

const char* DROP_TABLE = "DROP TABLE test_blob";

const char* CREATE_PROCEDURE =
        "CREATE PROCEDURE test_procedure(id INTEGER, char_data BLOB SUB_TYPE 1) "
        "AS BEGIN "
        "  INSERT INTO test_blob(id, char_data) VALUES (:id, :char_data);"
        "END";

const char* DROP_PROCEDURE = "DROP PROCEDURE test_procedure";

int main(void) {
    cleanUp();
    tryAutocommit();
    cleanUp();
    tryManageable();

    // now in different order - to be 100% sure
    /*cleanUp();
    tryManageable();
    cleanUp();
    tryAutocommit();*/

    cleanUp();
    tryWrapped();
    cleanUp();
}

void cleanUp() {
    cout << endl << "cleanup..." << endl;
    isc_db_handle db = attach();
    isc_tr_handle tr = startManageableTransaction(&db);
    executeStatement(DROP_TABLE, &tr, &db, true);
    executeStatement(DROP_PROCEDURE, &tr, &db, true);
    commit(&tr);
    detach(&db);
}

void tryManageable() {
    cout << endl << "In manageable transaction..." << endl;

    isc_db_handle db = attach();
    isc_tr_handle tr = startManageableTransaction(&db);
    if (executeStatement(CREATE_TABLE, &tr, &db)) {
        cout << "Successfully created table" << endl;
    }
    if (executeStatement(CREATE_PROCEDURE, &tr, &db)) {
        cout << "Successfully created procedure" << endl;
    }
    if (executeStatement(DROP_TABLE, &tr, &db)) {
        cout << "Successfully dropped table" << endl;
    }
    if (executeStatement(DROP_PROCEDURE, &tr, &db)) {
        cout << "Successfully dropped procedure" << endl;
    }
    commit(&tr);
    detach(&db);
}

void tryWrapped() {
    cout << endl << "In wrapped transaction..." << endl;

    isc_db_handle db = attach();
    isc_tr_handle tr = startManageableTransaction(&db);
    if (executeStatement(CREATE_TABLE, &tr, &db)) {
        cout << "Successfully created table" << endl;
    }
    commit(&tr);
    if (!tr) tr = startManageableTransaction(&db);
    if (executeStatement(CREATE_PROCEDURE, &tr, &db)) {
        cout << "Successfully created procedure" << endl;
    }
    commit(&tr);
    if (!tr) tr = startManageableTransaction(&db);
    if (executeStatement(DROP_TABLE, &tr, &db)) {
        cout << "Successfully dropped table" << endl;
    }
    commit(&tr);
    if (!tr) tr = startManageableTransaction(&db);
    if (executeStatement(DROP_PROCEDURE, &tr, &db)) {
        cout << "Successfully dropped procedure" << endl;
    }
    commit(&tr);
    detach(&db);
}

void tryAutocommit() {
    cout << endl << "In auto-commit transaction..." << endl;

    isc_db_handle db = attach();
    isc_tr_handle tr = startAutoCommitTransaction(&db);
    if (executeStatement(CREATE_TABLE, &tr, &db)) {
        cout << "Successfully created table" << endl;
    }
    if (executeStatement(CREATE_PROCEDURE, &tr, &db)) {
        cout << "Successfully created procedure" << endl;
    }
    if (executeStatement(DROP_TABLE, &tr, &db)) {
        cout << "Successfully dropped table" << endl;
    }
    if (executeStatement(DROP_PROCEDURE, &tr, &db)) {
        cout << "Successfully dropped procedure" << endl;
    }
    // Yep, I do manual commit here as well.
    commit(&tr);
    detach(&db);
}

isc_db_handle attach() {
    short dpb_length=20;
    char dpb[]= {
            isc_dpb_version1,
            isc_dpb_user_name,
            6,
            'S','Y','S','D','B','A',
            isc_dpb_password,
            9,
            'm','a','s','t','e','r','k','e','y'
    };
    ISC_STATUS status_vector[20];
    isc_db_handle db = 0;

    isc_attach_database(status_vector, strlen(db_name), db_name, &db, dpb_length, dpb);
    checkError(status_vector);
    return db;
}

bool detach(isc_db_handle* db) {
    if (*db) {
        ISC_STATUS status_vector[20];
        isc_detach_database(status_vector, db);
        return checkError(status_vector);
    }
    return true;
}

bool executeStatement(const char* query, isc_tr_handle* tr, isc_db_handle* db, bool quiet) {
    ISC_STATUS status_vector[20];
    isc_dsql_execute_immediate(status_vector, db, tr, 0, query, 1, NULL);
    return checkError(status_vector, quiet);
}

isc_tr_handle startManageableTransaction(isc_db_handle* db) {
    static char isc_tbp[] = {
            isc_tpb_version3,
            isc_tpb_write,
            isc_tpb_concurrency,
            isc_tpb_wait
    };

    isc_tr_handle tr = 0;
    ISC_STATUS status_vector[20];
    isc_start_transaction(status_vector, &tr, 1, db, (unsigned short) sizeof(isc_tbp), isc_tbp);
    checkError(status_vector);
    return tr;
}

isc_tr_handle startAutoCommitTransaction(isc_db_handle* db) {
    static char isc_tbp[] = {
            isc_tpb_version3,
            isc_tpb_write,
            isc_tpb_concurrency,
            isc_tpb_wait,
            isc_tpb_autocommit
    };

    isc_tr_handle tr = 0;
    ISC_STATUS status_vector[20];
    isc_start_transaction(status_vector, &tr, 1, db, (unsigned short) sizeof(isc_tbp), isc_tbp);
    checkError(status_vector);
    return tr;
}

bool commit(isc_tr_handle* tr) {
    ISC_STATUS status_vector[20];
    isc_commit_transaction(status_vector, tr);
    return checkError(status_vector);
}

bool checkError(ISC_STATUS* status_vector, bool quiet) {
    if (status_vector[0] == 1 && status_vector[1])
    {
        if (!quiet) {
            isc_print_status(status_vector);
        }
        return false;
    } else {
        return true;
    }
}


------------------------------------------------------------------------------
Firebird-Devel mailing list, web interface at 
https://lists.sourceforge.net/lists/listinfo/firebird-devel

Reply via email to