28
28
#include "ext/standard/info.h"
29
29
#include "pdo/php_pdo.h"
30
30
#include "pdo/php_pdo_driver.h"
31
+ #include "pdo/php_pdo_error.h"
31
32
#include "php_pdo_firebird.h"
32
33
#include "php_pdo_firebird_int.h"
34
+ #include "firebird_driver_arginfo.h"
33
35
34
36
static int firebird_alloc_prepare_stmt (pdo_dbh_t * , const zend_string * , XSQLDA * , isc_stmt_handle * , HashTable * );
35
37
@@ -700,48 +702,31 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
700
702
static bool _firebird_begin_transaction (pdo_dbh_t * dbh ) /* {{{ */
701
703
{
702
704
pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
703
- char tpb [8 ] = { isc_tpb_version3 }, * ptpb = tpb + 1 ;
704
- #ifdef abies_0
705
- if (dbh -> transaction_flags & PDO_TRANS_ISOLATION_LEVEL ) {
706
- if (dbh -> transaction_flags & PDO_TRANS_READ_UNCOMMITTED ) {
707
- /* this is a poor fit, but it's all we have */
705
+ char tpb [5 ] = { isc_tpb_version3 }, * ptpb = tpb + strlen (tpb );
706
+
707
+ switch (H -> txn_isolation_level ) {
708
+ case PDO_FB_READ_COMMITTED :
708
709
* ptpb ++ = isc_tpb_read_committed ;
709
710
* ptpb ++ = isc_tpb_rec_version ;
710
- dbh -> transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL ^PDO_TRANS_READ_UNCOMMITTED );
711
- } else if (dbh -> transaction_flags & PDO_TRANS_READ_COMMITTED ) {
712
- * ptpb ++ = isc_tpb_read_committed ;
713
- * ptpb ++ = isc_tpb_no_rec_version ;
714
- dbh -> transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL ^PDO_TRANS_READ_COMMITTED );
715
- } else if (dbh -> transaction_flags & PDO_TRANS_REPEATABLE_READ ) {
716
- * ptpb ++ = isc_tpb_concurrency ;
717
- dbh -> transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL ^PDO_TRANS_REPEATABLE_READ );
718
- } else {
711
+ break ;
712
+
713
+ case PDO_FB_SERIALIZABLE :
719
714
* ptpb ++ = isc_tpb_consistency ;
720
- dbh -> transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL ^PDO_TRANS_SERIALIZABLE );
721
- }
722
- }
715
+ break ;
723
716
724
- if (dbh -> transaction_flags & PDO_TRANS_ACCESS_MODE ) {
725
- if (dbh -> transaction_flags & PDO_TRANS_READONLY ) {
726
- * ptpb ++ = isc_tpb_read ;
727
- dbh -> transaction_flags &= ~(PDO_TRANS_ACCESS_MODE ^PDO_TRANS_READONLY );
728
- } else {
729
- * ptpb ++ = isc_tpb_write ;
730
- dbh -> transaction_flags &= ~(PDO_TRANS_ACCESS_MODE ^PDO_TRANS_READWRITE );
731
- }
717
+ case PDO_FB_REPEATABLE_READ :
718
+ default :
719
+ * ptpb ++ = isc_tpb_concurrency ;
720
+ break ;
732
721
}
733
722
734
- if (dbh -> transaction_flags & PDO_TRANS_CONFLICT_RESOLUTION ) {
735
- if (dbh -> transaction_flags & PDO_TRANS_RETRY ) {
736
- * ptpb ++ = isc_tpb_wait ;
737
- dbh -> transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION ^PDO_TRANS_RETRY );
738
- } else {
739
- * ptpb ++ = isc_tpb_nowait ;
740
- dbh -> transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION ^PDO_TRANS_ABORT );
741
- }
723
+ if (H -> is_writable_txn ) {
724
+ * ptpb ++ = isc_tpb_write ;
725
+ } else {
726
+ * ptpb ++ = isc_tpb_read ;
742
727
}
743
- #endif
744
- if (isc_start_transaction (H -> isc_status , & H -> tr , 1 , & H -> db , (unsigned short )(ptpb - tpb ), tpb )) {
728
+
729
+ if (isc_start_transaction (H -> isc_status , & H -> tr , 1 , & H -> db , (unsigned short )(ptpb - tpb ), tpb )) {
745
730
RECORD_ERROR (dbh );
746
731
return false;
747
732
}
@@ -882,6 +867,7 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
882
867
{
883
868
pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
884
869
bool bval ;
870
+ zend_long lval ;
885
871
886
872
switch (attr ) {
887
873
case PDO_ATTR_AUTOCOMMIT :
@@ -962,6 +948,36 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
962
948
zend_string_release_ex (str , 0 );
963
949
}
964
950
return true;
951
+
952
+ case PDO_FB_TRANSACTION_ISOLATION_LEVEL :
953
+ {
954
+ if (!pdo_get_long_param (& lval , val )) {
955
+ return false;
956
+ }
957
+ if (H -> txn_isolation_level != lval ) {
958
+ if (lval == PDO_FB_READ_COMMITTED ||
959
+ lval == PDO_FB_REPEATABLE_READ ||
960
+ lval == PDO_FB_SERIALIZABLE
961
+ ) {
962
+ if (H -> tr && H -> in_manually_txn ) {
963
+ H -> last_app_error = "Cannot change isolation level while a transaction is already open" ;
964
+ return false;
965
+ }
966
+ H -> txn_isolation_level = lval ;
967
+ if (dbh -> auto_commit ) {
968
+ if (H -> tr && !firebird_commit_transaction (dbh , false)) {
969
+ return false;
970
+ }
971
+ if (!_firebird_begin_transaction (dbh )) {
972
+ return false;
973
+ }
974
+ }
975
+ } else {
976
+ return false;
977
+ }
978
+ }
979
+ }
980
+ return true;
965
981
}
966
982
return false;
967
983
}
@@ -1062,6 +1078,64 @@ static void pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval
1062
1078
}
1063
1079
/* }}} */
1064
1080
1081
+ /* change transaction access mode. writable or readonly */
1082
+ static void change_transaction_access_mode (INTERNAL_FUNCTION_PARAMETERS , bool writable ) /* {{{ */
1083
+ {
1084
+ pdo_dbh_t * dbh ;
1085
+
1086
+ ZEND_PARSE_PARAMETERS_NONE ();
1087
+
1088
+ dbh = Z_PDO_DBH_P (ZEND_THIS );
1089
+ PDO_CONSTRUCT_CHECK ;
1090
+
1091
+ pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
1092
+
1093
+ if (H -> is_writable_txn == writable ) {
1094
+ RETURN_TRUE ;
1095
+ }
1096
+
1097
+ if (H -> tr && H -> in_manually_txn ) {
1098
+ H -> last_app_error = "Cannot change access mode while a transaction is already open" ;
1099
+ RETURN_FALSE ;
1100
+ }
1101
+ H -> is_writable_txn = writable ;
1102
+ if (dbh -> auto_commit ) {
1103
+ if (H -> tr && !firebird_commit_transaction (dbh , false)) {
1104
+ RETURN_FALSE ;
1105
+ }
1106
+ if (!_firebird_begin_transaction (dbh )) {
1107
+ RETURN_FALSE ;
1108
+ }
1109
+ }
1110
+
1111
+ RETURN_TRUE ;
1112
+ }
1113
+ /* }}} */
1114
+
1115
+ /* {{{ change transaction mode to writable */
1116
+ PHP_METHOD (PDO_Firebird_Ext , fbWritable )
1117
+ {
1118
+ change_transaction_access_mode (INTERNAL_FUNCTION_PARAM_PASSTHRU , true);
1119
+ }
1120
+ /* }}} */
1121
+
1122
+ /* {{{ change transaction mode to readonly */
1123
+ PHP_METHOD (PDO_Firebird_Ext , fbReadonly )
1124
+ {
1125
+ change_transaction_access_mode (INTERNAL_FUNCTION_PARAM_PASSTHRU , false);
1126
+ }
1127
+ /* }}} */
1128
+
1129
+ static const zend_function_entry * pdo_firebird_get_driver_methods (pdo_dbh_t * dbh , int kind )
1130
+ {
1131
+ switch (kind ) {
1132
+ case PDO_DBH_DRIVER_METHOD_KIND_DBH :
1133
+ return class_PDO_Firebird_Ext_methods ;
1134
+ default :
1135
+ return NULL ;
1136
+ }
1137
+ }
1138
+
1065
1139
/* {{{ firebird_in_manually_transaction */
1066
1140
static bool firebird_in_manually_transaction (pdo_dbh_t * dbh )
1067
1141
{
@@ -1083,7 +1157,7 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */
1083
1157
pdo_firebird_fetch_error_func ,
1084
1158
firebird_handle_get_attribute ,
1085
1159
NULL , /* check_liveness */
1086
- NULL , /* get driver methods */
1160
+ pdo_firebird_get_driver_methods ,
1087
1161
NULL , /* request shutdown */
1088
1162
firebird_in_manually_transaction ,
1089
1163
NULL /* get gc */
@@ -1167,6 +1241,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /*
1167
1241
}
1168
1242
1169
1243
H -> in_manually_txn = 0 ;
1244
+ H -> is_writable_txn = 1 ;
1170
1245
if (dbh -> auto_commit && !H -> tr ) {
1171
1246
ret = _firebird_begin_transaction (dbh );
1172
1247
}
0 commit comments