Skip to content

Commit 9382363

Browse files
committed
Added transaction isolation level and access mode settings
1 parent 10b02c5 commit 9382363

File tree

3 files changed

+98
-33
lines changed

3 files changed

+98
-33
lines changed

ext/pdo_firebird/firebird_driver.c

Lines changed: 79 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -702,48 +702,36 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
702702
static bool _firebird_begin_transaction(pdo_dbh_t *dbh) /* {{{ */
703703
{
704704
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
705-
char tpb[8] = { isc_tpb_version3 }, *ptpb = tpb+1;
706-
#ifdef abies_0
707-
if (dbh->transaction_flags & PDO_TRANS_ISOLATION_LEVEL) {
708-
if (dbh->transaction_flags & PDO_TRANS_READ_UNCOMMITTED) {
709-
/* this is a poor fit, but it's all we have */
705+
char tpb[6] = { isc_tpb_version3 }, *ptpb = tpb + strlen(tpb);
706+
707+
switch (H->txn_isolation_level) {
708+
case PDO_FB_READ_UNCOMMITTED:
710709
*ptpb++ = isc_tpb_read_committed;
711710
*ptpb++ = isc_tpb_rec_version;
712-
dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_UNCOMMITTED);
713-
} else if (dbh->transaction_flags & PDO_TRANS_READ_COMMITTED) {
711+
break;
712+
case PDO_FB_READ_COMMITTED:
714713
*ptpb++ = isc_tpb_read_committed;
715714
*ptpb++ = isc_tpb_no_rec_version;
716-
dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_COMMITTED);
717-
} else if (dbh->transaction_flags & PDO_TRANS_REPEATABLE_READ) {
718-
*ptpb++ = isc_tpb_concurrency;
719-
dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_REPEATABLE_READ);
720-
} else {
715+
*ptpb++ = isc_tpb_nowait;
716+
break;
717+
718+
case PDO_FB_SERIALIZABLE:
721719
*ptpb++ = isc_tpb_consistency;
722-
dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_SERIALIZABLE);
723-
}
724-
}
720+
break;
725721

726-
if (dbh->transaction_flags & PDO_TRANS_ACCESS_MODE) {
727-
if (dbh->transaction_flags & PDO_TRANS_READONLY) {
728-
*ptpb++ = isc_tpb_read;
729-
dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);
730-
} else {
731-
*ptpb++ = isc_tpb_write;
732-
dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READWRITE);
733-
}
722+
case PDO_FB_REPEATABLE_READ:
723+
default:
724+
*ptpb++ = isc_tpb_concurrency;
725+
break;
734726
}
735727

736-
if (dbh->transaction_flags & PDO_TRANS_CONFLICT_RESOLUTION) {
737-
if (dbh->transaction_flags & PDO_TRANS_RETRY) {
738-
*ptpb++ = isc_tpb_wait;
739-
dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_RETRY);
740-
} else {
741-
*ptpb++ = isc_tpb_nowait;
742-
dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_ABORT);
743-
}
728+
if (H->is_write_txn) {
729+
*ptpb++ = isc_tpb_write;
730+
} else {
731+
*ptpb++ = isc_tpb_read;
744732
}
745-
#endif
746-
if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb-tpb), tpb)) {
733+
734+
if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb - tpb), tpb)) {
747735
RECORD_ERROR(dbh);
748736
return false;
749737
}
@@ -884,6 +872,7 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
884872
{
885873
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
886874
bool bval;
875+
zend_long lval;
887876

888877
switch (attr) {
889878
case PDO_ATTR_AUTOCOMMIT:
@@ -964,6 +953,62 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
964953
zend_string_release_ex(str, 0);
965954
}
966955
return true;
956+
957+
case PDO_FB_TRANSACTION_ISOLATION_LEVEL:
958+
{
959+
if (!pdo_get_long_param(&lval, val)) {
960+
return false;
961+
}
962+
if (H->txn_isolation_level != lval) {
963+
if (lval == PDO_FB_READ_UNCOMMITTED ||
964+
lval == PDO_FB_READ_COMMITTED ||
965+
lval == PDO_FB_REPEATABLE_READ ||
966+
lval == PDO_FB_SERIALIZABLE
967+
) {
968+
if (H->tr && H->in_manually_txn) {
969+
/* */
970+
H->last_app_error = "Cannot change isolation level while a transaction is already open";
971+
return false;
972+
}
973+
H->txn_isolation_level = lval;
974+
if (dbh->auto_commit) {
975+
if (H->tr && !_firebird_commit_transaction(dbh, false)) {
976+
return false;
977+
}
978+
if (!_firebird_begin_transaction(dbh)) {
979+
return false;
980+
}
981+
}
982+
} else {
983+
return false;
984+
}
985+
}
986+
}
987+
return true;
988+
989+
case PDO_FB_WRITE_TRANSACTION:
990+
{
991+
if (!pdo_get_bool_param(&bval, val)) {
992+
return false;
993+
}
994+
if (H->is_write_txn ^ bval) {
995+
if (H->tr && H->in_manually_txn) {
996+
/* */
997+
H->last_app_error = "Cannot change transaction mode while a transaction is already open";
998+
return false;
999+
}
1000+
H->is_write_txn = bval;
1001+
if (dbh->auto_commit) {
1002+
if (H->tr && !_firebird_commit_transaction(dbh, false)) {
1003+
return false;
1004+
}
1005+
if (!_firebird_begin_transaction(dbh)) {
1006+
return false;
1007+
}
1008+
}
1009+
}
1010+
}
1011+
return true;
9671012
}
9681013
return false;
9691014
}
@@ -1169,6 +1214,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /*
11691214
}
11701215

11711216
H->in_manually_txn = 0;
1217+
H->is_write_txn = 1;
11721218
if (dbh->auto_commit && !H->tr) {
11731219
ret = _firebird_begin_transaction(dbh);
11741220
}

ext/pdo_firebird/pdo_firebird.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */
5757
REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_DATE_FORMAT", (zend_long) PDO_FB_ATTR_DATE_FORMAT);
5858
REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_TIME_FORMAT", (zend_long) PDO_FB_ATTR_TIME_FORMAT);
5959
REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_TIMESTAMP_FORMAT", (zend_long) PDO_FB_ATTR_TIMESTAMP_FORMAT);
60+
REGISTER_PDO_CLASS_CONST_LONG("FB_TRANSACTION_ISOLATION_LEVEL", (zend_long) PDO_FB_TRANSACTION_ISOLATION_LEVEL);
61+
REGISTER_PDO_CLASS_CONST_LONG("FB_READ_UNCOMMITTED", (zend_long) PDO_FB_READ_UNCOMMITTED);
62+
REGISTER_PDO_CLASS_CONST_LONG("FB_READ_COMMITTED", (zend_long) PDO_FB_READ_COMMITTED);
63+
REGISTER_PDO_CLASS_CONST_LONG("FB_REPEATABLE_READ", (zend_long) PDO_FB_REPEATABLE_READ);
64+
REGISTER_PDO_CLASS_CONST_LONG("FB_SERIALIZABLE", (zend_long) PDO_FB_SERIALIZABLE);
65+
REGISTER_PDO_CLASS_CONST_LONG("FB_WRITE_TRANSACTION", (zend_long) PDO_FB_WRITE_TRANSACTION);
6066

6167
if (FAILURE == php_pdo_register_driver(&pdo_firebird_driver)) {
6268
return FAILURE;

ext/pdo_firebird/php_pdo_firebird_int.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef struct {
7070
/* the transaction handle */
7171
isc_tr_handle tr;
7272
bool in_manually_txn:1;
73+
bool is_write_txn:1;
7374

7475
/* the last error that didn't come from the API */
7576
char const *last_app_error;
@@ -86,6 +87,8 @@ typedef struct {
8687

8788
unsigned _reserved:29;
8889

90+
/* transaction isolation level */
91+
zend_ulong txn_isolation_level;
8992
} pdo_firebird_db_handle;
9093

9194

@@ -132,6 +135,16 @@ enum {
132135
PDO_FB_ATTR_DATE_FORMAT = PDO_ATTR_DRIVER_SPECIFIC,
133136
PDO_FB_ATTR_TIME_FORMAT,
134137
PDO_FB_ATTR_TIMESTAMP_FORMAT,
138+
139+
/* transaction isolation level */
140+
PDO_FB_TRANSACTION_ISOLATION_LEVEL,
141+
PDO_FB_READ_UNCOMMITTED,
142+
PDO_FB_READ_COMMITTED,
143+
PDO_FB_REPEATABLE_READ,
144+
PDO_FB_SERIALIZABLE,
145+
146+
/* transaction mode */
147+
PDO_FB_WRITE_TRANSACTION,
135148
};
136149

137150
#endif /* PHP_PDO_FIREBIRD_INT_H */

0 commit comments

Comments
 (0)