From f45e6364b46d40a747d183ee11cbaa5c8743a141 Mon Sep 17 00:00:00 2001 From: Adam Baratz Date: Fri, 27 Jan 2017 18:41:11 -0500 Subject: [PATCH] Add test coverage for bug #72969 This was not an issue with pdo_dblib, but rather with FreeTDS. FreeTDS has been fixed as of the fc820490336c50d5c175d2a15327383256add4c9 on that repo. These tests will be skipped if a version of FreeTDS with that issue is present. I only cleaned up this commit for pushing. For fixing the FreeTDS issue and writing corresponding pdo_dblib tests, thanks to: Jeff Farr --- ext/pdo_dblib/tests/batch_stmt_ins_exec.phpt | 62 ++++++++ .../tests/batch_stmt_ins_sel_up_del.phpt | 73 +++++++++ ext/pdo_dblib/tests/batch_stmt_ins_up.phpt | 59 +++++++ ext/pdo_dblib/tests/batch_stmt_rowcount.phpt | 144 ++++++++++++++++++ .../tests/batch_stmt_transaction.phpt | 111 ++++++++++++++ ext/pdo_dblib/tests/batch_stmt_try.phpt | 99 ++++++++++++ ext/pdo_dblib/tests/config.inc | 23 +++ 7 files changed, 571 insertions(+) create mode 100644 ext/pdo_dblib/tests/batch_stmt_ins_exec.phpt create mode 100644 ext/pdo_dblib/tests/batch_stmt_ins_sel_up_del.phpt create mode 100644 ext/pdo_dblib/tests/batch_stmt_ins_up.phpt create mode 100644 ext/pdo_dblib/tests/batch_stmt_rowcount.phpt create mode 100644 ext/pdo_dblib/tests/batch_stmt_transaction.phpt create mode 100644 ext/pdo_dblib/tests/batch_stmt_try.phpt diff --git a/ext/pdo_dblib/tests/batch_stmt_ins_exec.phpt b/ext/pdo_dblib/tests/batch_stmt_ins_exec.phpt new file mode 100644 index 0000000000..5d218051e8 --- /dev/null +++ b/ext/pdo_dblib/tests/batch_stmt_ins_exec.phpt @@ -0,0 +1,62 @@ +--TEST-- +PDO_DBLIB: driver supports a batch of queries containing SELECT, INSERT, UPDATE, EXEC statements +--SKIPIF-- + +--FILE-- +query("create table #php_pdo(id int); "); +$db->query( +"create proc php_pdo_exec_select_proc as " . +"begin " . +" insert into #php_pdo values(2), (3), (4); " . +" select * from #php_pdo; " . +"end; " +); + +// now lets get some results +$stmt = $db->query( +"insert into #php_pdo values(1); " . +"exec php_pdo_exec_select_proc; " . +"drop table #php_pdo; " . +"drop procedure php_pdo_exec_select_proc; "); + +// check results from the insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the exec +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop table +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop procedure +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +?> +--EXPECT-- +int(1) +bool(true) +int(-1) +bool(true) +int(-1) +bool(true) +int(-1) +bool(false) +int(-1) +bool(false) diff --git a/ext/pdo_dblib/tests/batch_stmt_ins_sel_up_del.phpt b/ext/pdo_dblib/tests/batch_stmt_ins_sel_up_del.phpt new file mode 100644 index 0000000000..e2c5f6ac47 --- /dev/null +++ b/ext/pdo_dblib/tests/batch_stmt_ins_sel_up_del.phpt @@ -0,0 +1,73 @@ +--TEST-- +PDO_DBLIB: driver supports a batch of queries containing SELECT, INSERT, UPDATE statements +--SKIPIF-- + +--FILE-- +query( +"create table #php_pdo(id int);" . +"insert into #php_pdo values(1), (2), (3);" . +"select * from #php_pdo;" . +"update #php_pdo set id = 4;" . +"delete from #php_pdo;" . +"select * from #php_pdo;" . +"drop table #php_pdo;" +); + +// check results from the create table +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the first insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the update +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the delete +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +?> +--EXPECT-- +int(-1) +bool(true) +int(3) +bool(true) +int(-1) +bool(true) +int(3) +bool(true) +int(3) +bool(true) +int(0) +bool(true) +int(-1) +bool(false) +int(-1) +bool(false) diff --git a/ext/pdo_dblib/tests/batch_stmt_ins_up.phpt b/ext/pdo_dblib/tests/batch_stmt_ins_up.phpt new file mode 100644 index 0000000000..8f162e7a6d --- /dev/null +++ b/ext/pdo_dblib/tests/batch_stmt_ins_up.phpt @@ -0,0 +1,59 @@ +--TEST-- +PDO_DBLIB: driver supports multiple queries in a single \PDO::query() call that doesn't return any rowsets +--SKIPIF-- + +--FILE-- +query( +"create table #php_pdo(id int);" . +"insert into #php_pdo values(1), (2), (3);" . +"update #php_pdo set id = 1;" . +"insert into #php_pdo values(2);" . +"drop table #php_pdo;" +); + +// check results from the create table +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the first insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the update +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the second insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +?> +--EXPECT-- +int(-1) +bool(true) +int(3) +bool(true) +int(3) +bool(true) +int(1) +bool(true) +int(-1) +bool(false) +int(-1) +bool(false) diff --git a/ext/pdo_dblib/tests/batch_stmt_rowcount.phpt b/ext/pdo_dblib/tests/batch_stmt_rowcount.phpt new file mode 100644 index 0000000000..287a7e3528 --- /dev/null +++ b/ext/pdo_dblib/tests/batch_stmt_rowcount.phpt @@ -0,0 +1,144 @@ +--TEST-- +PDO_DBLIB: driver supports SET ROWCOUNT and SELECT @@ROWCOUNT in batch statements +--SKIPIF-- + +--FILE-- +query( +"create table #php_pdo(id int); " . +"set rowcount 2; " . +"insert into #php_pdo values(1), (2), (3); " . +"insert into #php_pdo values(4), (5), (6); " . +"update #php_pdo set id = 4; " . +"select @@rowcount; " +); + +// check results from the create table +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the set rowcount +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the first insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the second insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the update +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select rowcount +var_dump($stmt->fetchAll()); +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// now cleanup and check that the results are expected +$stmt = $db->query("set rowcount 0;" . +"select * from #php_pdo;" . +"delete from #php_pdo;" . +"drop table #php_pdo;" +); + +// check results from set rowcount +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select +var_dump($stmt->fetchAll()); +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the delete +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +?> +--EXPECT-- +int(-1) +bool(true) +int(-1) +bool(true) +int(2) +bool(true) +int(2) +bool(true) +int(2) +bool(true) +array(1) { + [0]=> + array(2) { + ["computed"]=> + int(2) + [0]=> + int(2) + } +} +int(-1) +bool(false) +int(-1) +bool(false) +int(-1) +bool(true) +array(4) { + [0]=> + array(2) { + ["id"]=> + int(4) + [0]=> + int(4) + } + [1]=> + array(2) { + ["id"]=> + int(4) + [0]=> + int(4) + } + [2]=> + array(2) { + ["id"]=> + int(4) + [0]=> + int(4) + } + [3]=> + array(2) { + ["id"]=> + int(5) + [0]=> + int(5) + } +} +int(-1) +bool(true) +int(4) +bool(true) +int(-1) +bool(false) +int(-1) +bool(false) diff --git a/ext/pdo_dblib/tests/batch_stmt_transaction.phpt b/ext/pdo_dblib/tests/batch_stmt_transaction.phpt new file mode 100644 index 0000000000..d811f6786f --- /dev/null +++ b/ext/pdo_dblib/tests/batch_stmt_transaction.phpt @@ -0,0 +1,111 @@ +--TEST-- +PDO_DBLIB: driver supports a batch of queries containing SELECT, INSERT, UPDATE statements +--SKIPIF-- + +--FILE-- +query( +"create table #php_pdo(id int);" . +"insert into #php_pdo values(1), (2), (3);" . +"select * from #php_pdo;" . +"begin transaction;" . +"update #php_pdo set id = 4;" . +"rollback transaction;" . +"select * from #php_pdo;" . +"delete from #php_pdo;" . +"drop table #php_pdo;" +); + +// check results from the create table +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the first insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from begin transaction +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the update +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from rollback +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select +var_dump($stmt->fetchAll()); +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the delete +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +?> +--EXPECT-- +int(-1) +bool(true) +int(3) +bool(true) +int(-1) +bool(true) +int(-1) +bool(true) +int(3) +bool(true) +int(-1) +bool(true) +array(3) { + [0]=> + array(2) { + ["id"]=> + int(1) + [0]=> + int(1) + } + [1]=> + array(2) { + ["id"]=> + int(2) + [0]=> + int(2) + } + [2]=> + array(2) { + ["id"]=> + int(3) + [0]=> + int(3) + } +} +int(-1) +bool(true) +int(3) +bool(true) +int(-1) +bool(false) +int(-1) +bool(false) diff --git a/ext/pdo_dblib/tests/batch_stmt_try.phpt b/ext/pdo_dblib/tests/batch_stmt_try.phpt new file mode 100644 index 0000000000..0f74d0b701 --- /dev/null +++ b/ext/pdo_dblib/tests/batch_stmt_try.phpt @@ -0,0 +1,99 @@ +--TEST-- +PDO_DBLIB: driver supports exceptions +--SKIPIF-- + +--FILE-- +query( +"create table #php_pdo(id int);" . +"insert into #php_pdo values(1), (2), (3);" . +"select * from #php_pdo;" . +"begin try " . +" update #php_pdo set id = 'f';" . +"end try " . +"begin catch " . +" throw;" . +"end catch " . +"select * from #php_pdo;" . +"delete from #php_pdo;" . +"drop table #php_pdo;" +); + +// check results from the create table +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the first insert +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the select +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from try +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the update +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that the update statement throws an error +try { + var_dump($stmt->rowCount()); + var_dump($stmt->nextRowset()); +} catch (PDOException $e) { + var_dump($e->getMessage()); +} + +// once an error is thrown, the batch is terminated. +// there should no results from here on +// check results from the select +var_dump($stmt->fetchAll()); +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the delete +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check results from the drop +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +// check that there are no more results +var_dump($stmt->rowCount()); +var_dump($stmt->nextRowset()); + +?> +--EXPECT-- +int(-1) +bool(true) +int(3) +bool(true) +int(-1) +bool(true) +int(-1) +bool(true) +int(0) +bool(true) +int(-1) +string(68) "SQLSTATE[HY000]: General error: PDO_DBLIB: dbresults() returned FAIL" +array(0) { +} +int(-1) +bool(false) +int(-1) +bool(false) +int(-1) +bool(false) +int(-1) +bool(false) diff --git a/ext/pdo_dblib/tests/config.inc b/ext/pdo_dblib/tests/config.inc index 3cc81f39b2..40e8bf6ff9 100644 --- a/ext/pdo_dblib/tests/config.inc +++ b/ext/pdo_dblib/tests/config.inc @@ -16,6 +16,29 @@ function get_tds_version() { return null; } +// bug #72969 reflects a bug with FreeTDS, not with pdo_dblib +// this function will version detect so the relevant tests can XFAILIF +function driver_supports_batch_statements_without_select($db) { + $version = $db->getAttribute(PDO::DBLIB_ATTR_VERSION); + + // assume driver doesn't have this bug if not using FreeTDS + if (!strstartswith($version, 'freetds ')) { + return true; + } + + // hasn't made it to numbered release yet + if (!strstartswith($version, 'freetds v1.1.dev.')) { + return false; + } + + // fc820490336c50d5c175d2a15327383256add4c9 was committed on the 5th + return intval(substr($version, -8)) >= 20161206; +} + +function strstartswith($haystack, $needle) { + return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false; +} + if (false !== getenv('PDO_DBLIB_TEST_DSN')) { $dsn = getenv('PDO_DBLIB_TEST_DSN'); } else { -- 2.40.0