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 <[email protected]> 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