-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Feature: Add transaction isolation level and mode settings to pdo_firebird
#12815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Add transaction isolation level and mode settings to pdo_firebird
#12815
Conversation
ext/pdo_firebird/firebird_driver.c
Outdated
) { | ||
H->txn_isolation_level = txn_isolation_level; | ||
} else { | ||
H->txn_isolation_level = PDO_FB_REPEATABLE_READ; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I make it an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took a closer look, and the ret
value is a mess. I don't know what it want to do by returning -1
.
I would like to leave this as is for now and fix it all together in a separate pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this case ever happen? The attribute should be controlled by the driver and only return valid values. So I would probably make this an assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value is set by users, so any value that is an int will come here. Therefore, it is quite possible that values other than the three constant values will be passed.
factory may need validation and errors as same as set attr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would possibly throw a ValueError as trying to use an invalid transaction isolation mode is a programming error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both the constructor and set attr have been fixed to cause a value error.
b7d932f
However, I am a little confused about whether it would be better to write zend_restore_error_handling
in pdo core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, zend_value_error
is better. I'll fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Could you please review it when you have time? |
ext/pdo_firebird/firebird_driver.c
Outdated
@@ -822,7 +827,7 @@ static bool firebird_handle_manually_begin(pdo_dbh_t *dbh) /* {{{ */ | |||
} | |||
} | |||
|
|||
if (!php_firebird_begin_transaction(dbh)) { | |||
if (!php_firebird_begin_transaction(dbh, /* manually */ false)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!php_firebird_begin_transaction(dbh, /* manually */ false)) { | |
if (!php_firebird_begin_transaction(dbh, /* auto commit mode */ false)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed on e1fd726
retain
comment was also difficult to understand, so I fixed it as well.
ext/pdo_firebird/firebird_driver.c
Outdated
pdo_raise_impl_error(dbh, NULL, "HY000", | ||
"Transaction isolation level must be PDO::FB_READ_COMMITTED, PDO::FB_REPEATABLE_READ, or PDO::PDO_FB_SERIALIZABLE"); | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd throw a ValueError instead, as this is a Firebird specific attribute.
ext/pdo_firebird/firebird_driver.c
Outdated
*ptpb++ = isc_tpb_write; | ||
dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READWRITE); | ||
/* isc_xxx are all 1 byte. */ | ||
char tpb[5] = { isc_tpb_version3 }, *ptpb = tpb + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
char tpb[5] = { isc_tpb_version3 }, *ptpb = tpb + 1; | |
/* tpb means "Transaction Parameter Buffer" */ | |
char tpb[] = { isc_tpb_version3 }; | |
char *ptpb = tpb + 1; |
The tpb might not be consistent across versions?
I don't really get how the pointer is being initialized and also why it is updated twice sometimes, as it will overwrite the table?
If this is intended, then using tpb[1] = isc_tpb_read_committed
is possibly easier to understand. But comments around the Interbase/Firebird API would be helpful as this is confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is not an API with the FB_ prefix, it seems safe to assume that there is no difference between versions. Therefore, there are no differences between versions in the tpb specifications.
I think I can write it a little more clearly, so I'll try rewriting it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to rewrite it a little easier to understand.
efa0d98
The setting add more 1 byte for read committed
, because firebird's read committed
supports multiple modes of behavior.
isc_tpb_rec_version
is the mode for reading from committed data.
The opposite setting is isc_tpb_no_rec_version
. This is a mode in which uncommitted data waits for it to be committed (or rolled back) and then read.
Detailed documentation on these:
https://docwiki.embarcadero.com/InterBase/2020/en/Specifying_Isolation_Level
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, when reading some times within a transaction, the phenomenon where different data is read due to updates by other transactions is called "Phantom Read".
(I deleted the comment about Phantom Read because it might have been difficult to understand.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Girgias
Using strlen on char arrays doesn't seem to work well on windows. (It may be wrong to use strlen for arrays in the first place.)
I rewrote it for now and the test passed, but which one seems better, the one using the pointer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this version is clearer
ext/pdo_firebird/firebird_driver.c
Outdated
) { | ||
H->txn_isolation_level = txn_isolation_level; | ||
} else { | ||
H->txn_isolation_level = PDO_FB_REPEATABLE_READ; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this case ever happen? The attribute should be controlled by the driver and only return valid values. So I would probably make this an assertion.
I made a mistake. It's late today, so I'll fix it tomorrow. |
cdca462
to
ac8516a
Compare
Passed! |
b887eea
to
55c7be2
Compare
ext/pdo_firebird/firebird_driver.c
Outdated
*/ | ||
case PDO_FB_READ_COMMITTED: | ||
tpb[2] = isc_tpb_read_committed; | ||
/* Not wait to commit indeterminate data. This option required only with `read committed`.*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* Not wait to commit indeterminate data. This option required only with `read committed`.*/ | |
/* Do not wait to commit indeterminate data. This option only required with `read committed`. */ |
Not sure what you mean by "indeterminate" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why the sentence is like this....Maybe I was tired.
It should have been a comment like this, I'll fix it.
Ignore indeterminate data from other transactions.
Indeterminate data from other transactions means data that has not been committed or rolled back in other transactions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
ext/pdo_firebird/firebird_driver.c
Outdated
) { | ||
H->txn_isolation_level = txn_isolation_level; | ||
} else { | ||
H->txn_isolation_level = PDO_FB_REPEATABLE_READ; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would possibly throw a ValueError as trying to use an invalid transaction isolation mode is a programming error.
a70544b
to
2cebb13
Compare
2cebb13
to
b3caa01
Compare
…B_TRANSACTION_ISOLATION_LEVEL.
b7d932f
to
04235aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me, can you add an entry to UPGRADING/NEWS? :)
zend_value_error("PDO::FB_TRANSACTION_ISOLATION_LEVEL must be a valid transaction isolation level " | ||
"(PDO::FB_READ_COMMITTED, PDO::FB_REPEATABLE_READ, or PDO::FB_SERIALIZABLE)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a possible follow-up suggestion to extract the common error message into a function so that they don't go out of sync.
Thanks! |
take2 of #12664
About Firebird transaction isolation levels
Firebird's transaction isolation level can only be set at the beginning of a transaction. Therefore, I saved the user's settings on the php side and used them when starting a transaction.
Default is
repeatable lead
.Firebird's
read committed
has three types of behaviorFor this pull request, I adopted 1, which is a common
read committed
.It is possible to switch between 2 and 3 by attribute value, but I have decided that there is no need to implement it yet as I do not know the demand.
About access mode
There are writable and read-only modes. Like isolation levels, this can only be set at the beginning of a transaction. In the same way, the setting value is retained on the php side.
Default is
writable
.Auto commit mode
Firebird's autocommit mode is emulated by PHP, which actually always has a transaction open. If a transaction in autocommit mode is run at a high isolation level, it will not be able to read any changes made by other transactions after
new PDO()
.Therefore, I made the autocommit mode to always work with
read committed
, regardless of the user's configured value.