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