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
dc3cfb2f
Commit
dc3cfb2f
authored
Oct 13, 2016
by
Sergei Morozov
Committed by
Marco Pivetta
Feb 04, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[DBAL-2546] Bind result variables after each execution in order to prevent string truncation
parent
7cd0589f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
13 deletions
+62
-13
MysqliStatement.php
lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
+29
-13
StatementTest.php
tests/Doctrine/Tests/DBAL/Functional/StatementTest.php
+33
-0
No files found.
lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
View file @
dc3cfb2f
...
...
@@ -168,9 +168,6 @@ class MysqliStatement implements \IteratorAggregate, Statement
if
(
null
===
$this
->
_columnNames
)
{
$meta
=
$this
->
_stmt
->
result_metadata
();
if
(
false
!==
$meta
)
{
// We have a result.
$this
->
_stmt
->
store_result
();
$columnNames
=
array
();
foreach
(
$meta
->
fetch_fields
()
as
$col
)
{
$columnNames
[]
=
$col
->
name
;
...
...
@@ -178,21 +175,40 @@ class MysqliStatement implements \IteratorAggregate, Statement
$meta
->
free
();
$this
->
_columnNames
=
$columnNames
;
$this
->
_rowBindedValues
=
array_fill
(
0
,
count
(
$columnNames
),
null
);
$refs
=
array
();
foreach
(
$this
->
_rowBindedValues
as
$key
=>
&
$value
)
{
$refs
[
$key
]
=&
$value
;
}
if
(
!
call_user_func_array
(
array
(
$this
->
_stmt
,
'bind_result'
),
$refs
))
{
throw
new
MysqliException
(
$this
->
_stmt
->
error
,
$this
->
_stmt
->
sqlstate
,
$this
->
_stmt
->
errno
);
}
}
else
{
$this
->
_columnNames
=
false
;
}
}
if
(
false
!==
$this
->
_columnNames
)
{
// Store result of every execution which has it. Otherwise it will be impossible
// to execute a new statement in case if the previous one has non-fetched rows
// @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html
$this
->
_stmt
->
store_result
();
// Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql,
// it will have to allocate as much memory as it may be needed for the given column type
// (e.g. for a LONGBLOB field it's 4 gigabytes)
// @link https://bugs.php.net/bug.php?id=51386#1270673122
//
// Make sure that the values are bound after each execution. Otherwise, if closeCursor() has been
// previously called on the statement, the values are unbound making the statement unusable.
//
// It's also important that row values are bound after _each_ call to store_result(). Otherwise,
// if mysqli is compiled with libmysql, subsequently fetched string values will get truncated
// to the length of the ones fetched during the previous execution.
$this
->
_rowBindedValues
=
array_fill
(
0
,
count
(
$this
->
_columnNames
),
null
);
$refs
=
array
();
foreach
(
$this
->
_rowBindedValues
as
$key
=>
&
$value
)
{
$refs
[
$key
]
=&
$value
;
}
if
(
!
call_user_func_array
(
array
(
$this
->
_stmt
,
'bind_result'
),
$refs
))
{
throw
new
MysqliException
(
$this
->
_stmt
->
error
,
$this
->
_stmt
->
sqlstate
,
$this
->
_stmt
->
errno
);
}
}
return
true
;
}
...
...
tests/Doctrine/Tests/DBAL/Functional/StatementTest.php
View file @
dc3cfb2f
...
...
@@ -53,4 +53,37 @@ class StatementTest extends \Doctrine\Tests\DbalFunctionalTestCase
$this
->
assertFalse
(
$value
);
}
public
function
testReuseStatementWithLongerResults
()
{
$sm
=
$this
->
_conn
->
getSchemaManager
();
$table
=
new
Table
(
'stmt_test_longer_results'
);
$table
->
addColumn
(
'param'
,
'string'
);
$table
->
addColumn
(
'val'
,
'text'
);
$sm
->
createTable
(
$table
);
$row1
=
array
(
'param'
=>
'param1'
,
'val'
=>
'X'
,
);
$this
->
_conn
->
insert
(
'stmt_test_longer_results'
,
$row1
);
$stmt
=
$this
->
_conn
->
prepare
(
'SELECT param, val FROM stmt_test_longer_results ORDER BY param'
);
$stmt
->
execute
();
$this
->
assertArraySubset
(
array
(
array
(
'param1'
,
'X'
),
),
$stmt
->
fetchAll
(
\PDO
::
FETCH_NUM
));
$row2
=
array
(
'param'
=>
'param2'
,
'val'
=>
'A bit longer value'
,
);
$this
->
_conn
->
insert
(
'stmt_test_longer_results'
,
$row2
);
$stmt
->
execute
();
$this
->
assertArraySubset
(
array
(
array
(
'param1'
,
'X'
),
array
(
'param2'
,
'A bit longer value'
),
),
$stmt
->
fetchAll
(
\PDO
::
FETCH_NUM
));
}
}
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