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
static bool firebird_commit_transaction (pdo_dbh_t * dbh , bool retain );
36
- static bool _firebird_rollback_transaction (pdo_dbh_t * dbh , bool retain );
38
+ static bool firebird_rollback_transaction (pdo_dbh_t * dbh , bool retain );
37
39
38
40
const char CHR_LETTER = 1 ;
39
41
const char CHR_DIGIT = 2 ;
@@ -480,7 +482,7 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */
480
482
if (dbh -> auto_commit ) {
481
483
firebird_commit_transaction (dbh , false);
482
484
} else {
483
- _firebird_rollback_transaction (dbh , false);
485
+ firebird_rollback_transaction (dbh , false);
484
486
}
485
487
}
486
488
H -> in_manually_txn = 0 ;
@@ -702,48 +704,31 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
702
704
static bool firebird_begin_transaction (pdo_dbh_t * dbh ) /* {{{ */
703
705
{
704
706
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 */
707
+ char tpb [5 ] = { isc_tpb_version3 }, * ptpb = tpb + strlen (tpb );
708
+
709
+ switch (H -> txn_isolation_level ) {
710
+ case PDO_FB_READ_COMMITTED :
710
711
* ptpb ++ = isc_tpb_read_committed ;
711
712
* 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 ) {
714
- * ptpb ++ = isc_tpb_read_committed ;
715
- * 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 {
713
+ break ;
714
+
715
+ case PDO_FB_SERIALIZABLE :
721
716
* ptpb ++ = isc_tpb_consistency ;
722
- dbh -> transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL ^PDO_TRANS_SERIALIZABLE );
723
- }
724
- }
717
+ break ;
725
718
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
- }
719
+ case PDO_FB_REPEATABLE_READ :
720
+ default :
721
+ * ptpb ++ = isc_tpb_concurrency ;
722
+ break ;
734
723
}
735
724
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
- }
725
+ if (H -> is_writable_txn ) {
726
+ * ptpb ++ = isc_tpb_write ;
727
+ } else {
728
+ * ptpb ++ = isc_tpb_read ;
744
729
}
745
- #endif
746
- if (isc_start_transaction (H -> isc_status , & H -> tr , 1 , & H -> db , (unsigned short )(ptpb - tpb ), tpb )) {
730
+
731
+ if (isc_start_transaction (H -> isc_status , & H -> tr , 1 , & H -> db , (unsigned short )(ptpb - tpb ), tpb )) {
747
732
RECORD_ERROR (dbh );
748
733
return false;
749
734
}
@@ -804,8 +789,8 @@ static bool firebird_handle_manually_commit(pdo_dbh_t *dbh) /* {{{ */
804
789
}
805
790
/* }}} */
806
791
807
- /* _firebird_rollback_transaction */
808
- static bool _firebird_rollback_transaction (pdo_dbh_t * dbh , bool retain ) /* {{{ */
792
+ /* firebird_rollback_transaction */
793
+ static bool firebird_rollback_transaction (pdo_dbh_t * dbh , bool retain ) /* {{{ */
809
794
{
810
795
pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
811
796
@@ -830,7 +815,7 @@ static bool firebird_handle_manually_rollback(pdo_dbh_t *dbh) /* {{{ */
830
815
{
831
816
pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
832
817
833
- if (!_firebird_rollback_transaction (dbh , dbh -> auto_commit )) {
818
+ if (!firebird_rollback_transaction (dbh , dbh -> auto_commit )) {
834
819
return false;
835
820
}
836
821
@@ -884,6 +869,7 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
884
869
{
885
870
pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
886
871
bool bval ;
872
+ zend_long lval ;
887
873
888
874
switch (attr ) {
889
875
case PDO_ATTR_AUTOCOMMIT :
@@ -964,6 +950,36 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
964
950
zend_string_release_ex (str , 0 );
965
951
}
966
952
return true;
953
+
954
+ case PDO_FB_TRANSACTION_ISOLATION_LEVEL :
955
+ {
956
+ if (!pdo_get_long_param (& lval , val )) {
957
+ return false;
958
+ }
959
+ if (H -> txn_isolation_level != lval ) {
960
+ if (lval == PDO_FB_READ_COMMITTED ||
961
+ lval == PDO_FB_REPEATABLE_READ ||
962
+ lval == PDO_FB_SERIALIZABLE
963
+ ) {
964
+ if (H -> tr && H -> in_manually_txn ) {
965
+ H -> last_app_error = "Cannot change isolation level while a transaction is already open" ;
966
+ return false;
967
+ }
968
+ H -> txn_isolation_level = lval ;
969
+ if (dbh -> auto_commit ) {
970
+ if (H -> tr && !firebird_commit_transaction (dbh , false)) {
971
+ return false;
972
+ }
973
+ if (!firebird_begin_transaction (dbh )) {
974
+ return false;
975
+ }
976
+ }
977
+ } else {
978
+ return false;
979
+ }
980
+ }
981
+ }
982
+ return true;
967
983
}
968
984
return false;
969
985
}
@@ -1064,6 +1080,71 @@ static void pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval
1064
1080
}
1065
1081
/* }}} */
1066
1082
1083
+ /* change transaction access mode. writable or readonly */
1084
+ static bool change_transaction_access_mode (pdo_dbh_t * dbh , bool writable ) /* {{{ */
1085
+ {
1086
+ pdo_firebird_db_handle * H = (pdo_firebird_db_handle * )dbh -> driver_data ;
1087
+
1088
+ if (H -> is_writable_txn == writable ) {
1089
+ return true;
1090
+ }
1091
+
1092
+ if (H -> tr && H -> in_manually_txn ) {
1093
+ H -> last_app_error = "Cannot change access mode while a transaction is already open" ;
1094
+ PDO_HANDLE_DBH_ERR ();
1095
+ return false;
1096
+ }
1097
+ H -> is_writable_txn = writable ;
1098
+ if (dbh -> auto_commit ) {
1099
+ if (H -> tr && !firebird_commit_transaction (dbh , false)) {
1100
+ return false;
1101
+ }
1102
+ if (!firebird_begin_transaction (dbh )) {
1103
+ return false;
1104
+ }
1105
+ }
1106
+ return true;
1107
+ }
1108
+ /* }}} */
1109
+
1110
+ /* {{{ change transaction mode to writable */
1111
+ PHP_METHOD (PDO_Firebird_Ext , fbWritable )
1112
+ {
1113
+ pdo_dbh_t * dbh ;
1114
+
1115
+ ZEND_PARSE_PARAMETERS_NONE ();
1116
+
1117
+ dbh = Z_PDO_DBH_P (ZEND_THIS );
1118
+ PDO_CONSTRUCT_CHECK ;
1119
+
1120
+ RETURN_BOOL (change_transaction_access_mode (dbh , true));
1121
+ }
1122
+ /* }}} */
1123
+
1124
+ /* {{{ change transaction mode to readonly */
1125
+ PHP_METHOD (PDO_Firebird_Ext , fbReadonly )
1126
+ {
1127
+ pdo_dbh_t * dbh ;
1128
+
1129
+ ZEND_PARSE_PARAMETERS_NONE ();
1130
+
1131
+ dbh = Z_PDO_DBH_P (ZEND_THIS );
1132
+ PDO_CONSTRUCT_CHECK ;
1133
+
1134
+ RETURN_BOOL (change_transaction_access_mode (dbh , false));
1135
+ }
1136
+ /* }}} */
1137
+
1138
+ static const zend_function_entry * pdo_firebird_get_driver_methods (pdo_dbh_t * dbh , int kind )
1139
+ {
1140
+ switch (kind ) {
1141
+ case PDO_DBH_DRIVER_METHOD_KIND_DBH :
1142
+ return class_PDO_Firebird_Ext_methods ;
1143
+ default :
1144
+ return NULL ;
1145
+ }
1146
+ }
1147
+
1067
1148
/* {{{ firebird_in_manually_transaction */
1068
1149
static bool firebird_in_manually_transaction (pdo_dbh_t * dbh )
1069
1150
{
@@ -1085,7 +1166,7 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */
1085
1166
pdo_firebird_fetch_error_func ,
1086
1167
firebird_handle_get_attribute ,
1087
1168
NULL , /* check_liveness */
1088
- NULL , /* get driver methods */
1169
+ pdo_firebird_get_driver_methods ,
1089
1170
NULL , /* request shutdown */
1090
1171
firebird_in_manually_transaction ,
1091
1172
NULL /* get gc */
@@ -1169,6 +1250,7 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /*
1169
1250
}
1170
1251
1171
1252
H -> in_manually_txn = 0 ;
1253
+ H -> is_writable_txn = 1 ;
1172
1254
if (dbh -> auto_commit && !H -> tr ) {
1173
1255
ret = firebird_begin_transaction (dbh );
1174
1256
}
0 commit comments