diff --git a/ext/pdo/tests/pdo_017.phpt b/ext/pdo/tests/pdo_017.phpt index bc514bff2c32b..d24aff1c15f32 100644 --- a/ext/pdo/tests/pdo_017.phpt +++ b/ext/pdo/tests/pdo_017.phpt @@ -8,7 +8,6 @@ $dir = getenv('REDIR_TEST_DIR'); if (false == $dir) die('skip no driver'); require_once $dir . 'pdo_test.inc'; PDOTest::skip(); -if (str_starts_with(getenv('PDOTEST_DSN'), "firebird")) die('xfail firebird driver does not behave as expected'); $db = PDOTest::factory(); try { diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index cbd7ee7cfd377..4bc74ceac0d7c 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -28,11 +28,11 @@ #include "ext/standard/info.h" #include "pdo/php_pdo.h" #include "pdo/php_pdo_driver.h" +#include "pdo/php_pdo_error.h" #include "php_pdo_firebird.h" #include "php_pdo_firebird_int.h" -static int firebird_alloc_prepare_stmt(pdo_dbh_t*, const zend_string*, XSQLDA*, isc_stmt_handle*, - HashTable*); +static int firebird_alloc_prepare_stmt(pdo_dbh_t*, const zend_string*, XSQLDA*, isc_stmt_handle*, HashTable*); const char CHR_LETTER = 1; const char CHR_DIGIT = 2; @@ -475,17 +475,14 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */ { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - if (dbh->in_txn) { + if (H->tr) { if (dbh->auto_commit) { - if (isc_commit_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - } + firebird_commit_transaction(dbh, false); } else { - if (isc_rollback_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - } + firebird_rollback_transaction(dbh, false); } } + H->in_manually_txn = 0; if (isc_detach_database(H->isc_status, &H->db)) { RECORD_ERROR(dbh); @@ -647,8 +644,8 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /* } /* commit if we're in auto_commit mode */ - if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); + if (dbh->auto_commit && !H->in_manually_txn) { + firebird_commit_transaction(dbh, true); } free_statement: @@ -700,52 +697,35 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un } /* }}} */ -/* called by PDO to start a transaction */ -static bool firebird_handle_begin(pdo_dbh_t *dbh) /* {{{ */ +/* _firebird_begin_transaction */ +static bool _firebird_begin_transaction(pdo_dbh_t *dbh) /* {{{ */ { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - char tpb[8] = { isc_tpb_version3 }, *ptpb = tpb+1; -#ifdef abies_0 - if (dbh->transaction_flags & PDO_TRANS_ISOLATION_LEVEL) { - if (dbh->transaction_flags & PDO_TRANS_READ_UNCOMMITTED) { - /* this is a poor fit, but it's all we have */ + char tpb[5] = { isc_tpb_version3 }, *ptpb = tpb + strlen(tpb); + + switch (H->txn_isolation_level) { + case PDO_FB_READ_COMMITTED: *ptpb++ = isc_tpb_read_committed; *ptpb++ = isc_tpb_rec_version; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_UNCOMMITTED); - } else if (dbh->transaction_flags & PDO_TRANS_READ_COMMITTED) { - *ptpb++ = isc_tpb_read_committed; - *ptpb++ = isc_tpb_no_rec_version; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_COMMITTED); - } else if (dbh->transaction_flags & PDO_TRANS_REPEATABLE_READ) { - *ptpb++ = isc_tpb_concurrency; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_REPEATABLE_READ); - } else { + break; + + case PDO_FB_SERIALIZABLE: *ptpb++ = isc_tpb_consistency; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_SERIALIZABLE); - } - } + break; - if (dbh->transaction_flags & PDO_TRANS_ACCESS_MODE) { - if (dbh->transaction_flags & PDO_TRANS_READONLY) { - *ptpb++ = isc_tpb_read; - dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY); - } else { - *ptpb++ = isc_tpb_write; - dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READWRITE); - } + case PDO_FB_REPEATABLE_READ: + default: + *ptpb++ = isc_tpb_concurrency; + break; } - if (dbh->transaction_flags & PDO_TRANS_CONFLICT_RESOLUTION) { - if (dbh->transaction_flags & PDO_TRANS_RETRY) { - *ptpb++ = isc_tpb_wait; - dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_RETRY); - } else { - *ptpb++ = isc_tpb_nowait; - dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_ABORT); - } + if (H->is_writable_txn) { + *ptpb++ = isc_tpb_write; + } else { + *ptpb++ = isc_tpb_read; } -#endif - if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb-tpb), tpb)) { + + if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb - tpb), tpb)) { RECORD_ERROR(dbh); return false; } @@ -753,28 +733,90 @@ static bool firebird_handle_begin(pdo_dbh_t *dbh) /* {{{ */ } /* }}} */ +/* called by PDO to start a transaction */ +static bool firebird_handle_manually_begin(pdo_dbh_t *dbh) /* {{{ */ +{ + pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; + + if (dbh->auto_commit && H->tr && !firebird_commit_transaction(dbh, false)) { + return false; + } + + if (!_firebird_begin_transaction(dbh)) { + return false; + } + + H->in_manually_txn = 1; + return true; +} +/* }}} */ + +/* firebird_commit_transaction */ +bool _firebird_commit_transaction(pdo_dbh_t *dbh, bool retain) /* {{{ */ +{ + pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; + + if (retain) { + if (isc_commit_retaining(H->isc_status, &H->tr)) { + RECORD_ERROR(dbh); + return false; + } + } else { + if (isc_commit_transaction(H->isc_status, &H->tr)) { + RECORD_ERROR(dbh); + return false; + } + } + + return true; +} +/* }}} */ + /* called by PDO to commit a transaction */ -static bool firebird_handle_commit(pdo_dbh_t *dbh) /* {{{ */ +static bool firebird_handle_manually_commit(pdo_dbh_t *dbh) /* {{{ */ { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - if (isc_commit_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); + if (!firebird_commit_transaction(dbh, dbh->auto_commit)) { return false; } + + H->in_manually_txn = 0; + return true; +} +/* }}} */ + +/* firebird_rollback_transaction */ +bool _firebird_rollback_transaction(pdo_dbh_t *dbh, bool retain) /* {{{ */ +{ + pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; + + if (retain) { + if (isc_rollback_retaining(H->isc_status, &H->tr)) { + RECORD_ERROR(dbh); + return false; + } + } else { + if (isc_rollback_transaction(H->isc_status, &H->tr)) { + RECORD_ERROR(dbh); + return false; + } + } + return true; } /* }}} */ /* called by PDO to rollback a transaction */ -static bool firebird_handle_rollback(pdo_dbh_t *dbh) /* {{{ */ +static bool firebird_handle_manually_rollback(pdo_dbh_t *dbh) /* {{{ */ { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - if (isc_rollback_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); + if (!firebird_rollback_transaction(dbh, dbh->auto_commit)) { return false; } + + H->in_manually_txn = 0; return true; } /* }}} */ @@ -792,16 +834,6 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql, return 0; } - /* start a new transaction implicitly if auto_commit is enabled and no transaction is open */ - if (dbh->auto_commit && !dbh->in_txn) { - /* dbh->transaction_flags = PDO_TRANS_READ_UNCOMMITTED; */ - - if (!firebird_handle_begin(dbh)) { - return 0; - } - dbh->in_txn = true; - } - /* allocate the statement */ if (isc_dsql_allocate_statement(H->isc_status, &H->db, s)) { RECORD_ERROR(dbh); @@ -834,6 +866,7 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; bool bval; + zend_long lval; switch (attr) { case PDO_ATTR_AUTOCOMMIT: @@ -844,19 +877,22 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * /* ignore if the new value equals the old one */ if (dbh->auto_commit ^ bval) { - if (dbh->in_txn) { - if (bval) { + if (bval) { + if (H->tr && H->in_manually_txn) { /* turning on auto_commit with an open transaction is illegal, because - we won't know what to do with it */ + we won't know what to do with it */ H->last_app_error = "Cannot enable auto-commit while a transaction is already open"; return false; - } else { - /* close the transaction */ - if (!firebird_handle_commit(dbh)) { - break; - } - dbh->in_txn = false; } + if (!H->tr && !_firebird_begin_transaction(dbh)) { + return false; + } + } else { + /* close the transaction */ + if (H->tr && !firebird_commit_transaction(dbh, false)) { + return false; + } + H->in_manually_txn = 0; } dbh->auto_commit = bval; } @@ -911,6 +947,60 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * zend_string_release_ex(str, 0); } return true; + + case PDO_FB_TRANSACTION_ISOLATION_LEVEL: + { + if (!pdo_get_long_param(&lval, val)) { + return false; + } + if (H->txn_isolation_level != lval) { + if (lval == PDO_FB_READ_COMMITTED || + lval == PDO_FB_REPEATABLE_READ || + lval == PDO_FB_SERIALIZABLE + ) { + if (H->tr && H->in_manually_txn) { + H->last_app_error = "Cannot change isolation level while a transaction is already open"; + return false; + } + H->txn_isolation_level = lval; + if (dbh->auto_commit) { + if (H->tr && !firebird_commit_transaction(dbh, false)) { + return false; + } + if (!_firebird_begin_transaction(dbh)) { + return false; + } + } + } else { + return false; + } + } + } + return true; + + case PDO_FB_WRITABLE_TRANSACTION: + { + if (!pdo_get_bool_param(&bval, val)) { + return false; + } + + if (H->is_writable_txn != bval) { + if (H->tr && H->in_manually_txn) { + H->last_app_error = "Cannot change access mode while a transaction is already open"; + return false; + } + H->is_writable_txn = bval; + if (dbh->auto_commit) { + if (H->tr && !firebird_commit_transaction(dbh, false)) { + return false; + } + if (!_firebird_begin_transaction(dbh)) { + return false; + } + } + } + } + return true; } return false; } @@ -983,6 +1073,14 @@ static int firebird_handle_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v case PDO_ATTR_FETCH_TABLE_NAMES: ZVAL_BOOL(val, H->fetch_table_names); return 1; + + case PDO_FB_TRANSACTION_ISOLATION_LEVEL: + ZVAL_LONG(val, H->txn_isolation_level); + return 1; + + case PDO_FB_WRITABLE_TRANSACTION: + ZVAL_BOOL(val, H->is_writable_txn); + return 1; } return 0; } @@ -1011,14 +1109,22 @@ static void pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval } /* }}} */ +/* {{{ firebird_in_manually_transaction */ +static bool firebird_in_manually_transaction(pdo_dbh_t *dbh) +{ + pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; + return H->tr && H->in_manually_txn; +} +/* }}} */ + static const struct pdo_dbh_methods firebird_methods = { /* {{{ */ firebird_handle_closer, firebird_handle_preparer, firebird_handle_doer, firebird_handle_quoter, - firebird_handle_begin, - firebird_handle_commit, - firebird_handle_rollback, + firebird_handle_manually_begin, + firebird_handle_manually_commit, + firebird_handle_manually_rollback, firebird_handle_set_attribute, NULL, /* last_id not supported */ pdo_firebird_fetch_error_func, @@ -1026,7 +1132,7 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */ NULL, /* check_liveness */ NULL, /* get driver methods */ NULL, /* request shutdown */ - NULL, /* in transaction, use PDO's internal tracking mechanism */ + firebird_in_manually_transaction, NULL /* get gc */ }; /* }}} */ @@ -1057,6 +1163,23 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* dbh->password = pestrdup(vars[5].optval, dbh->is_persistent); } + H->in_manually_txn = 0; + if (driver_options) { + H->is_writable_txn = pdo_attr_lval(driver_options, PDO_FB_WRITABLE_TRANSACTION, 1); + zend_long txn_isolation_level = pdo_attr_lval(driver_options, PDO_FB_TRANSACTION_ISOLATION_LEVEL, PDO_FB_REPEATABLE_READ); + if (txn_isolation_level == PDO_FB_READ_COMMITTED || + txn_isolation_level == PDO_FB_REPEATABLE_READ || + txn_isolation_level == PDO_FB_SERIALIZABLE + ) { + H->txn_isolation_level = txn_isolation_level; + } else { + H->txn_isolation_level = PDO_FB_REPEATABLE_READ; + } + } else { + H->is_writable_txn = 1; + H->txn_isolation_level = PDO_FB_REPEATABLE_READ; + } + do { static char const dpb_flags[] = { isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name }; @@ -1107,6 +1230,10 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* "HY000", H->isc_status[1], errmsg); } + if (dbh->auto_commit && !H->tr) { + ret = _firebird_begin_transaction(dbh); + } + if (!ret) { firebird_handle_closer(dbh); } diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 4ad51ab483d96..f0d43bbddb29b 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -177,8 +177,7 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */ ; } - /* commit? */ - if (stmt->dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) { + if (stmt->dbh->auto_commit && !S->H->in_manually_txn && !firebird_commit_transaction(stmt->dbh, true)) { break; } diff --git a/ext/pdo_firebird/pdo_firebird.c b/ext/pdo_firebird/pdo_firebird.c index efbebccb0e127..35cbfb51d9a06 100644 --- a/ext/pdo_firebird/pdo_firebird.c +++ b/ext/pdo_firebird/pdo_firebird.c @@ -57,6 +57,11 @@ PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */ REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_DATE_FORMAT", (zend_long) PDO_FB_ATTR_DATE_FORMAT); REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_TIME_FORMAT", (zend_long) PDO_FB_ATTR_TIME_FORMAT); REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_TIMESTAMP_FORMAT", (zend_long) PDO_FB_ATTR_TIMESTAMP_FORMAT); + REGISTER_PDO_CLASS_CONST_LONG("FB_TRANSACTION_ISOLATION_LEVEL", (zend_long) PDO_FB_TRANSACTION_ISOLATION_LEVEL); + REGISTER_PDO_CLASS_CONST_LONG("FB_READ_COMMITTED", (zend_long) PDO_FB_READ_COMMITTED); + REGISTER_PDO_CLASS_CONST_LONG("FB_REPEATABLE_READ", (zend_long) PDO_FB_REPEATABLE_READ); + REGISTER_PDO_CLASS_CONST_LONG("FB_SERIALIZABLE", (zend_long) PDO_FB_SERIALIZABLE); + REGISTER_PDO_CLASS_CONST_LONG("FB_WRITABLE_TRANSACTION", (zend_long) PDO_FB_WRITABLE_TRANSACTION); if (FAILURE == php_pdo_register_driver(&pdo_firebird_driver)) { return FAILURE; diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index 243163b8a08ad..7f0664ca0a280 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -59,6 +59,12 @@ typedef void (*info_func_t)(char*); # define PDO_FIREBIRD_HANDLE_INITIALIZER NULL #endif +extern bool _firebird_commit_transaction(pdo_dbh_t *dbh, bool retain); +#define firebird_commit_transaction(d,r) _firebird_commit_transaction(d, r) + +extern bool _firebird_rollback_transaction(pdo_dbh_t *dbh, bool retain); +#define firebird_rollback_transaction(d,r) _firebird_rollback_transaction(d, r) + typedef struct { /* the result of the last API call */ @@ -69,6 +75,8 @@ typedef struct { /* the transaction handle */ isc_tr_handle tr; + bool in_manually_txn:1; + bool is_writable_txn:1; /* the last error that didn't come from the API */ char const *last_app_error; @@ -85,6 +93,8 @@ typedef struct { unsigned _reserved:29; + /* transaction isolation level */ + zend_ulong txn_isolation_level; } pdo_firebird_db_handle; @@ -131,6 +141,15 @@ enum { PDO_FB_ATTR_DATE_FORMAT = PDO_ATTR_DRIVER_SPECIFIC, PDO_FB_ATTR_TIME_FORMAT, PDO_FB_ATTR_TIMESTAMP_FORMAT, + + /* transaction isolation level */ + PDO_FB_TRANSACTION_ISOLATION_LEVEL, + PDO_FB_READ_COMMITTED, + PDO_FB_REPEATABLE_READ, + PDO_FB_SERIALIZABLE, + + /** transaction access mode */ + PDO_FB_WRITABLE_TRANSACTION, }; #endif /* PHP_PDO_FIREBIRD_INT_H */ diff --git a/ext/pdo_firebird/tests/bug_47415.phpt b/ext/pdo_firebird/tests/bug_47415.phpt index 8349a1d50fe5d..9fb5eb660f791 100644 --- a/ext/pdo_firebird/tests/bug_47415.phpt +++ b/ext/pdo_firebird/tests/bug_47415.phpt @@ -15,8 +15,6 @@ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $dbh->exec('CREATE TABLE test47415 (idx int NOT NULL PRIMARY KEY, txt VARCHAR(20))'); $dbh->exec('INSERT INTO test47415 VALUES(0, \'String0\')'); -$dbh->commit(); - $query = "SELECT idx, txt FROM test47415 ORDER by idx"; $idx = $txt = 0; $stmt = $dbh->prepare($query); @@ -31,8 +29,6 @@ var_dump($stmt->rowCount()); $stmt = $dbh->prepare('DELETE FROM test47415'); $stmt->execute(); -$dbh->commit(); - unset($stmt); unset($dbh); ?> diff --git a/ext/pdo_firebird/tests/bug_48877.phpt b/ext/pdo_firebird/tests/bug_48877.phpt index e3cb6e93518d8..4415b24ad8c7f 100644 --- a/ext/pdo_firebird/tests/bug_48877.phpt +++ b/ext/pdo_firebird/tests/bug_48877.phpt @@ -17,7 +17,6 @@ $dbh->exec('CREATE TABLE test48877 (A integer)'); $dbh->exec("INSERT INTO test48877 VALUES ('1')"); $dbh->exec("INSERT INTO test48877 VALUES ('2')"); $dbh->exec("INSERT INTO test48877 VALUES ('3')"); -$dbh->commit(); $query = "SELECT * FROM test48877 WHERE A = :paramno"; @@ -32,7 +31,6 @@ var_dump($stmt->rowCount()); $stmt = $dbh->prepare('DELETE FROM test48877'); $stmt->execute(); -$dbh->commit(); unset($stmt); unset($dbh); diff --git a/ext/pdo_firebird/tests/bug_53280.phpt b/ext/pdo_firebird/tests/bug_53280.phpt index 2a4c19a44aa8c..d8615cb03a9d4 100644 --- a/ext/pdo_firebird/tests/bug_53280.phpt +++ b/ext/pdo_firebird/tests/bug_53280.phpt @@ -13,7 +13,6 @@ require("testdb.inc"); $dbh->exec('CREATE TABLE test53280(A VARCHAR(30), B VARCHAR(30), C VARCHAR(30))'); $dbh->exec("INSERT INTO test53280 VALUES ('A', 'B', 'C')"); -$dbh->commit(); $stmt1 = "SELECT B FROM test53280 WHERE A = ? AND B = ?"; $stmt2 = "SELECT B, C FROM test53280 WHERE A = ? AND B = ?"; @@ -28,7 +27,6 @@ $stmth1->execute(array('A', 'B')); $rows = $stmth1->fetchAll(); // <------- segfault var_dump($rows); -$dbh->commit(); unset($stmth1); unset($stmth2); unset($stmt); diff --git a/ext/pdo_firebird/tests/bug_62024.phpt b/ext/pdo_firebird/tests/bug_62024.phpt index e46fad61fdad8..2c351421d26c6 100644 --- a/ext/pdo_firebird/tests/bug_62024.phpt +++ b/ext/pdo_firebird/tests/bug_62024.phpt @@ -14,8 +14,6 @@ require("testdb.inc"); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $dbh->exec("CREATE TABLE test62024 (ID INTEGER NOT NULL, TEXT VARCHAR(10))"); -$dbh->commit(); - //start actual test $sql = "insert into test62024 (id, text) values (?, ?)"; @@ -30,15 +28,11 @@ var_dump($res); $res = $sttmt->execute($args_err); var_dump($res); -$dbh->commit(); - //teardown test data $sttmt = $dbh->prepare('DELETE FROM test62024'); $sttmt->execute(); -$dbh->commit(); - unset($sttmt); unset($dbh); diff --git a/ext/pdo_firebird/tests/bug_64037.phpt b/ext/pdo_firebird/tests/bug_64037.phpt index a86fe5f10914e..f1034a4dacef9 100644 --- a/ext/pdo_firebird/tests/bug_64037.phpt +++ b/ext/pdo_firebird/tests/bug_64037.phpt @@ -17,8 +17,6 @@ $dbh->exec("INSERT INTO test64037 (ID, TEXT, COST) VALUES (1, 'test', -1.0)"); $dbh->exec("INSERT INTO test64037 (ID, TEXT, COST) VALUES (2, 'test', -0.99)"); $dbh->exec("INSERT INTO test64037 (ID, TEXT, COST) VALUES (3, 'test', -1.01)"); -$dbh->commit(); - $query = "SELECT * from test64037 order by ID"; $stmt = $dbh->prepare($query); $stmt->execute(); @@ -31,8 +29,6 @@ var_dump($rows[2]['COST']); $stmt = $dbh->prepare('DELETE FROM test64037'); $stmt->execute(); -$dbh->commit(); - unset($stmt); unset($dbh); diff --git a/ext/pdo_firebird/tests/ddl2.phpt b/ext/pdo_firebird/tests/ddl2.phpt new file mode 100644 index 0000000000000..5b46e60c999f5 --- /dev/null +++ b/ext/pdo_firebird/tests/ddl2.phpt @@ -0,0 +1,36 @@ +--TEST-- +PDO_Firebird: DDL/transactions 2 +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- + +--ENV-- +LSAN_OPTIONS=detect_leaks=0 +--FILE-- +exec("CREATE TABLE test_ddl2 (val int)"); + +$dbh->beginTransaction(); +$dbh->exec("INSERT INTO test_ddl2 (val) VALUES (120)"); +$dbh->exec("CREATE TABLE test_ddl2_2 (val INT)"); +$dbh->rollback(); + +$result = $dbh->query("SELECT * FROM test_ddl2"); +foreach ($result as $r) { + var_dump($r); +} + +unset($dbh); +echo "done\n"; +?> +--CLEAN-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); +@$dbh->exec('DROP TABLE test_ddl2'); +@$dbh->exec('DROP TABLE test_ddl2_2'); +?> +--EXPECT-- +done diff --git a/ext/pdo_firebird/tests/payload_test.phpt b/ext/pdo_firebird/tests/payload_test.phpt index 0638e47e7e13f..e093d5a831763 100644 --- a/ext/pdo_firebird/tests/payload_test.phpt +++ b/ext/pdo_firebird/tests/payload_test.phpt @@ -16,6 +16,9 @@ $dsn = "firebird:dbname=inet://$address/test"; $username = 'SYSDBA'; $password = 'masterkey'; -new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); +new PDO($dsn, $username, $password, [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_AUTOCOMMIT => false, +]); ?> --EXPECT-- diff --git a/ext/pdo_firebird/tests/rowCount.phpt b/ext/pdo_firebird/tests/rowCount.phpt index bf3a9be0b49de..5604223ec4cc3 100644 --- a/ext/pdo_firebird/tests/rowCount.phpt +++ b/ext/pdo_firebird/tests/rowCount.phpt @@ -15,7 +15,6 @@ $dbh->exec('CREATE TABLE test_rowcount (A VARCHAR(10))'); $dbh->exec("INSERT INTO test_rowcount VALUES ('A')"); $dbh->exec("INSERT INTO test_rowcount VALUES ('A')"); $dbh->exec("INSERT INTO test_rowcount VALUES ('B')"); -$dbh->commit(); $query = "SELECT * FROM test_rowcount WHERE A = ?"; @@ -29,14 +28,11 @@ var_dump($stmt->rowCount()); $stmt = $dbh->prepare('UPDATE test_rowcount SET A="A" WHERE A != ?'); $stmt->execute(array('A')); var_dump($stmt->rowCount()); -$dbh->commit(); $stmt = $dbh->prepare('DELETE FROM test_rowcount'); $stmt->execute(); var_dump($stmt->rowCount()); -$dbh->commit(); - unset($stmt); unset($dbh); diff --git a/ext/pdo_firebird/tests/transaction_access_mode.phpt b/ext/pdo_firebird/tests/transaction_access_mode.phpt new file mode 100644 index 0000000000000..3c9d41c5c53e9 --- /dev/null +++ b/ext/pdo_firebird/tests/transaction_access_mode.phpt @@ -0,0 +1,114 @@ +--TEST-- +PDO_Firebird: transaction access mode +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- + +--ENV-- +LSAN_OPTIONS=detect_leaks=0 +--FILE-- + true, 'label' => 'writable'], + ['val' => false, 'label' => 'readonly'], +]; + +echo "Set attr in construct\n"; + +foreach ($values as $value) { + $dbh = new PDO( + PDO_FIREBIRD_TEST_DSN, + PDO_FIREBIRD_TEST_USER, + PDO_FIREBIRD_TEST_PASS, + [ + PDO::FB_WRITABLE_TRANSACTION => $value['val'], + ], + ); + + if ($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION) === $value['val']) { + echo "OK: {$value['label']}\n"; + } else { + echo "NG: {$value['label']}\n"; + } + + unset($dbh); +} + +echo "\n"; +echo "Set attr in setAttribute and behavior check\n"; + +$dbh = new PDO( + PDO_FIREBIRD_TEST_DSN, + PDO_FIREBIRD_TEST_USER, + PDO_FIREBIRD_TEST_PASS, +); + +$dbh->query("CREATE TABLE {$table} (val int)"); + +var_dump($dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, true)); + +if ($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION) === true) { + echo "OK: writable\n"; +} else { + echo "NG: writable\n"; +} +$dbh->query("INSERT INTO {$table} VALUES (12)"); +$r = $dbh->query("SELECT * FROM {$table}"); +foreach ($r as $row) { + var_dump($row); +} + +var_dump($dbh->setAttribute(PDO::FB_WRITABLE_TRANSACTION, false)); + +if ($dbh->getAttribute(PDO::FB_WRITABLE_TRANSACTION) === false) { + echo "OK: readonly\n"; +} else { + echo "NG: readonly\n"; +} +try { + $dbh->query("INSERT INTO {$table} VALUES (19)"); +} catch (PDOException $e) { + echo "error with readonly\n"; +} +$r = $dbh->query("SELECT * FROM {$table}"); +foreach ($r as $row) { + var_dump($row); +} + +unset($dbh); +?> +--CLEAN-- +exec('DROP TABLE transaction_access_mode'); +unset($dbh); +?> +--EXPECT-- +Set attr in construct +OK: writable +OK: readonly + +Set attr in setAttribute and behavior check +bool(true) +OK: writable +array(2) { + ["VAL"]=> + int(12) + [0]=> + int(12) +} +bool(true) +OK: readonly +error with readonly +array(2) { + ["VAL"]=> + int(12) + [0]=> + int(12) +} diff --git a/ext/pdo_firebird/tests/transaction_isolation_level.phpt b/ext/pdo_firebird/tests/transaction_isolation_level.phpt new file mode 100644 index 0000000000000..0a6ed41e43fb4 --- /dev/null +++ b/ext/pdo_firebird/tests/transaction_isolation_level.phpt @@ -0,0 +1,78 @@ +--TEST-- +PDO_Firebird: transaction isolation level +--EXTENSIONS-- +pdo_firebird +--SKIPIF-- + +--ENV-- +LSAN_OPTIONS=detect_leaks=0 +--FILE-- + $level, + ], + ); + + if ($dbh->getAttribute(PDO::FB_TRANSACTION_ISOLATION_LEVEL) === $level) { + echo "OK: {$levelStr}\n"; + } else { + echo "NG: {$levelStr}\n"; + } + + unset($dbh); +} + +echo "\n"; +echo "Set attr in setAttribute\n"; + +$dbh = new PDO( + PDO_FIREBIRD_TEST_DSN, + PDO_FIREBIRD_TEST_USER, + PDO_FIREBIRD_TEST_PASS, +); + +foreach ($levelStrs as $levelStr) { + $level = constant($levelStr); + + var_dump($dbh->setAttribute(PDO::FB_TRANSACTION_ISOLATION_LEVEL, $level)); + + if ($dbh->getAttribute(PDO::FB_TRANSACTION_ISOLATION_LEVEL) === $level) { + echo "OK: {$levelStr}\n"; + } else { + echo "NG: {$levelStr}\n"; + } +} + +unset($dbh); +?> +--EXPECT-- +Set attr in construct +OK: PDO::FB_READ_COMMITTED +OK: PDO::FB_REPEATABLE_READ +OK: PDO::FB_SERIALIZABLE + +Set attr in setAttribute +bool(true) +OK: PDO::FB_READ_COMMITTED +bool(true) +OK: PDO::FB_REPEATABLE_READ +bool(true) +OK: PDO::FB_SERIALIZABLE