Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
7e93a36e
Commit
7e93a36e
authored
Jan 16, 2017
by
Sergei Morozov
Committed by
Marco Pivetta
Feb 04, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[DBAL-2546] Prevent exception when fetching from closed cursor
parent
be045c2c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
95 additions
and
10 deletions
+95
-10
DB2Statement.php
lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php
+22
-1
MysqliStatement.php
lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
+16
-0
OCI8Statement.php
lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
+34
-0
SQLSrvStatement.php
lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php
+22
-0
StatementTest.php
tests/Doctrine/Tests/DBAL/Functional/StatementTest.php
+1
-9
No files found.
lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php
View file @
7e93a36e
...
...
@@ -48,6 +48,13 @@ class DB2Statement implements \IteratorAggregate, Statement
*/
private
$_defaultFetchMode
=
\PDO
::
FETCH_BOTH
;
/**
* Indicates whether the statement is in the state when fetching results is possible
*
* @var bool
*/
private
$result
=
false
;
/**
* DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG
*
...
...
@@ -105,7 +112,13 @@ class DB2Statement implements \IteratorAggregate, Statement
$this
->
_bindParam
=
array
();
return
db2_free_result
(
$this
->
_stmt
);
if
(
!
db2_free_result
(
$this
->
_stmt
))
{
return
false
;
}
$this
->
result
=
false
;
return
true
;
}
/**
...
...
@@ -164,6 +177,8 @@ class DB2Statement implements \IteratorAggregate, Statement
throw
new
DB2Exception
(
db2_stmt_errormsg
());
}
$this
->
result
=
true
;
return
$retval
;
}
...
...
@@ -194,6 +209,12 @@ class DB2Statement implements \IteratorAggregate, Statement
*/
public
function
fetch
(
$fetchMode
=
null
)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if
(
!
$this
->
result
)
{
return
false
;
}
$fetchMode
=
$fetchMode
?:
$this
->
_defaultFetchMode
;
switch
(
$fetchMode
)
{
case
\PDO
::
FETCH_BOTH
:
...
...
lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
View file @
7e93a36e
...
...
@@ -80,6 +80,13 @@ class MysqliStatement implements \IteratorAggregate, Statement
*/
protected
$_defaultFetchMode
=
PDO
::
FETCH_BOTH
;
/**
* Indicates whether the statement is in the state when fetching results is possible
*
* @var bool
*/
private
$result
=
false
;
/**
* @param \mysqli $conn
* @param string $prepareString
...
...
@@ -209,6 +216,8 @@ class MysqliStatement implements \IteratorAggregate, Statement
}
}
$this
->
result
=
true
;
return
true
;
}
...
...
@@ -256,6 +265,12 @@ class MysqliStatement implements \IteratorAggregate, Statement
*/
public
function
fetch
(
$fetchMode
=
null
)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if
(
!
$this
->
result
)
{
return
false
;
}
$values
=
$this
->
_fetch
();
if
(
null
===
$values
)
{
return
false
;
...
...
@@ -341,6 +356,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
public
function
closeCursor
()
{
$this
->
_stmt
->
free_result
();
$this
->
result
=
false
;
return
true
;
}
...
...
lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
View file @
7e93a36e
...
...
@@ -80,6 +80,13 @@ class OCI8Statement implements \IteratorAggregate, Statement
*/
private
$boundValues
=
array
();
/**
* Indicates whether the statement is in the state when fetching results is possible
*
* @var bool
*/
private
$result
=
false
;
/**
* Creates a new OCI8Statement that uses the given connection handle and SQL statement.
*
...
...
@@ -176,12 +183,19 @@ class OCI8Statement implements \IteratorAggregate, Statement
*/
public
function
closeCursor
()
{
// not having the result means there's nothing to close
if
(
!
$this
->
result
)
{
return
true
;
}
// emulate it by fetching and discarding rows, similarly to what PDO does in this case
// @link http://php.net/manual/en/pdostatement.closecursor.php
// @link https://github.com/php/php-src/blob/php-7.0.11/ext/pdo/pdo_stmt.c#L2075
// deliberately do not consider multiple result sets, since doctrine/dbal doesn't support them
while
(
oci_fetch
(
$this
->
_sth
));
$this
->
result
=
false
;
return
true
;
}
...
...
@@ -235,6 +249,8 @@ class OCI8Statement implements \IteratorAggregate, Statement
throw
OCI8Exception
::
fromErrorInfo
(
$this
->
errorInfo
());
}
$this
->
result
=
true
;
return
$ret
;
}
...
...
@@ -263,6 +279,12 @@ class OCI8Statement implements \IteratorAggregate, Statement
*/
public
function
fetch
(
$fetchMode
=
null
)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if
(
!
$this
->
result
)
{
return
false
;
}
$fetchMode
=
$fetchMode
?:
$this
->
_defaultFetchMode
;
if
(
!
isset
(
self
::
$fetchModeMap
[
$fetchMode
]))
{
throw
new
\InvalidArgumentException
(
"Invalid fetch style: "
.
$fetchMode
);
...
...
@@ -292,6 +314,12 @@ class OCI8Statement implements \IteratorAggregate, Statement
$fetchStructure
=
OCI_FETCHSTATEMENT_BY_COLUMN
;
}
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if
(
!
$this
->
result
)
{
return
array
();
}
oci_fetch_all
(
$this
->
_sth
,
$result
,
0
,
-
1
,
self
::
$fetchModeMap
[
$fetchMode
]
|
OCI_RETURN_NULLS
|
$fetchStructure
|
OCI_RETURN_LOBS
);
...
...
@@ -308,6 +336,12 @@ class OCI8Statement implements \IteratorAggregate, Statement
*/
public
function
fetchColumn
(
$columnIndex
=
0
)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if
(
!
$this
->
result
)
{
return
false
;
}
$row
=
oci_fetch_array
(
$this
->
_sth
,
OCI_NUM
|
OCI_RETURN_NULLS
|
OCI_RETURN_LOBS
);
if
(
false
===
$row
)
{
...
...
lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php
View file @
7e93a36e
...
...
@@ -98,6 +98,13 @@ class SQLSrvStatement implements IteratorAggregate, Statement
*/
private
$lastInsertId
;
/**
* Indicates whether the statement is in the state when fetching results is possible
*
* @var bool
*/
private
$result
=
false
;
/**
* Append to any INSERT query to retrieve the last insert id.
*
...
...
@@ -150,12 +157,19 @@ class SQLSrvStatement implements IteratorAggregate, Statement
*/
public
function
closeCursor
()
{
// not having the result means there's nothing to close
if
(
!
$this
->
result
)
{
return
true
;
}
// emulate it by fetching and discarding rows, similarly to what PDO does in this case
// @link http://php.net/manual/en/pdostatement.closecursor.php
// @link https://github.com/php/php-src/blob/php-7.0.11/ext/pdo/pdo_stmt.c#L2075
// deliberately do not consider multiple result sets, since doctrine/dbal doesn't support them
while
(
sqlsrv_fetch
(
$this
->
stmt
));
$this
->
result
=
false
;
return
true
;
}
...
...
@@ -211,6 +225,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
sqlsrv_fetch
(
$this
->
stmt
);
$this
->
lastInsertId
->
setId
(
sqlsrv_get_field
(
$this
->
stmt
,
0
));
}
$this
->
result
=
true
;
}
/**
...
...
@@ -240,6 +256,12 @@ class SQLSrvStatement implements IteratorAggregate, Statement
*/
public
function
fetch
(
$fetchMode
=
null
)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if
(
!
$this
->
result
)
{
return
false
;
}
$args
=
func_get_args
();
$fetchMode
=
$fetchMode
?:
$this
->
defaultFetchMode
;
...
...
tests/Doctrine/Tests/DBAL/Functional/StatementTest.php
View file @
7e93a36e
...
...
@@ -44,15 +44,7 @@ class StatementTest extends \Doctrine\Tests\DbalFunctionalTestCase
$stmt
->
execute
();
$stmt
->
closeCursor
();
try
{
$value
=
$stmt
->
fetchColumn
();
}
catch
(
\Exception
$e
)
{
// some adapters trigger PHP error or throw adapter-specific exception in case of fetching
// from a closed cursor, which still proves that it has been closed
return
;
}
$this
->
assertFalse
(
$value
);
$this
->
assertFalse
(
$stmt
->
fetchColumn
());
}
public
function
testReuseStatementWithLongerResults
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment