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
70340133
Unverified
Commit
70340133
authored
Sep 28, 2018
by
Sergei Morozov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented handling BLOBs represented as stream resources for IBM DB2
parent
091e2642
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
118 additions
and
31 deletions
+118
-31
DB2Statement.php
lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php
+109
-18
BlobTest.php
tests/Doctrine/Tests/DBAL/Functional/BlobTest.php
+9
-13
No files found.
lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php
View file @
70340133
...
...
@@ -13,8 +13,10 @@ use ReflectionObject;
use
ReflectionProperty
;
use
stdClass
;
use
const
CASE_LOWER
;
use
const
DB2_BINARY
;
use
const
DB2_CHAR
;
use
const
DB2_LONG
;
use
const
DB2_PARAM_FILE
;
use
const
DB2_PARAM_IN
;
use
function
array_change_key_case
;
use
function
db2_bind_param
;
...
...
@@ -28,14 +30,21 @@ use function db2_num_fields;
use
function
db2_num_rows
;
use
function
db2_stmt_error
;
use
function
db2_stmt_errormsg
;
use
function
error_get_last
;
use
function
fclose
;
use
function
func_get_args
;
use
function
func_num_args
;
use
function
fwrite
;
use
function
gettype
;
use
function
is_object
;
use
function
is_resource
;
use
function
is_string
;
use
function
ksort
;
use
function
sprintf
;
use
function
stream_copy_to_stream
;
use
function
stream_get_meta_data
;
use
function
strtolower
;
use
function
tmpfile
;
class
DB2Statement
implements
IteratorAggregate
,
Statement
{
...
...
@@ -45,6 +54,14 @@ class DB2Statement implements IteratorAggregate, Statement
/** @var mixed[] */
private
$bindParam
=
[];
/**
* Map of LOB parameter positions to the tuples containing reference to the variable bound to the driver statement
* and the temporary file handle bound to the underlying statement
*
* @var mixed[][]
*/
private
$lobs
=
[];
/** @var string Name of the default class to instantiate when fetching class instances. */
private
$defaultFetchClass
=
'\stdClass'
;
...
...
@@ -61,16 +78,6 @@ class DB2Statement implements IteratorAggregate, Statement
*/
private
$result
=
false
;
/**
* DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG
*
* @var int[]
*/
static
private
$typeMap
=
[
ParameterType
::
INTEGER
=>
DB2_LONG
,
ParameterType
::
STRING
=>
DB2_CHAR
,
];
/**
* @param resource $stmt
*/
...
...
@@ -92,21 +99,48 @@ class DB2Statement implements IteratorAggregate, Statement
*/
public
function
bindParam
(
$column
,
&
$variable
,
$type
=
ParameterType
::
STRING
,
$length
=
null
)
{
$this
->
bindParam
[
$column
]
=&
$variable
;
switch
(
$type
)
{
case
ParameterType
::
INTEGER
:
$this
->
bind
(
$column
,
$variable
,
DB2_PARAM_IN
,
DB2_LONG
);
break
;
if
(
$type
&&
isset
(
self
::
$typeMap
[
$type
]))
{
$type
=
self
::
$typeMap
[
$type
];
}
else
{
$type
=
DB2_CHAR
;
}
case
ParameterType
::
LARGE_OBJECT
:
if
(
isset
(
$this
->
lobs
[
$column
]))
{
[,
$handle
]
=
$this
->
lobs
[
$column
];
fclose
(
$handle
)
;
}
if
(
!
db2_bind_param
(
$this
->
stmt
,
$column
,
'variable'
,
DB2_PARAM_IN
,
$type
))
{
throw
new
DB2Exception
(
db2_stmt_errormsg
());
$handle
=
$this
->
createTemporaryFile
();
$path
=
stream_get_meta_data
(
$handle
)[
'uri'
];
$this
->
bind
(
$column
,
$path
,
DB2_PARAM_FILE
,
DB2_BINARY
);
$this
->
lobs
[
$column
]
=
[
&
$variable
,
$handle
];
break
;
default
:
$this
->
bind
(
$column
,
$variable
,
DB2_PARAM_IN
,
DB2_CHAR
);
break
;
}
return
true
;
}
/**
* @param int|string $parameter Parameter position or name
* @param mixed $variable
*
* @throws DB2Exception
*/
private
function
bind
(
$parameter
,
&
$variable
,
int
$parameterType
,
int
$dataType
)
:
void
{
$this
->
bindParam
[
$parameter
]
=&
$variable
;
if
(
!
db2_bind_param
(
$this
->
stmt
,
$parameter
,
'variable'
,
$parameterType
,
$dataType
))
{
throw
new
DB2Exception
(
db2_stmt_errormsg
());
}
}
/**
* {@inheritdoc}
*/
...
...
@@ -177,8 +211,24 @@ class DB2Statement implements IteratorAggregate, Statement
}
}
foreach
(
$this
->
lobs
as
[
$source
,
$target
])
{
if
(
is_resource
(
$source
))
{
$this
->
copyStreamToStream
(
$source
,
$target
);
continue
;
}
$this
->
writeStringToStream
(
$source
,
$target
);
}
$retval
=
db2_execute
(
$this
->
stmt
,
$params
);
foreach
(
$this
->
lobs
as
[,
$handle
])
{
fclose
(
$handle
);
}
$this
->
lobs
=
[];
if
(
$retval
===
false
)
{
throw
new
DB2Exception
(
db2_stmt_errormsg
());
}
...
...
@@ -372,4 +422,45 @@ class DB2Statement implements IteratorAggregate, Statement
return
$destinationClass
;
}
/**
* @return resource
*
* @throws DB2Exception
*/
private
function
createTemporaryFile
()
{
$handle
=
@
tmpfile
();
if
(
$handle
===
false
)
{
throw
new
DB2Exception
(
'Could not create temporary file: '
.
error_get_last
()[
'message'
]);
}
return
$handle
;
}
/**
* @param resource $source
* @param resource $target
*
* @throws DB2Exception
*/
private
function
copyStreamToStream
(
$source
,
$target
)
:
void
{
if
(
@
stream_copy_to_stream
(
$source
,
$target
)
===
false
)
{
throw
new
DB2Exception
(
'Could not copy source stream to temporary file: '
.
error_get_last
()[
'message'
]);
}
}
/**
* @param resource $target
*
* @throws DB2Exception
*/
private
function
writeStringToStream
(
string
$string
,
$target
)
:
void
{
if
(
@
fwrite
(
$target
,
$string
)
===
false
)
{
throw
new
DB2Exception
(
'Could not write string to temporary file: '
.
error_get_last
()[
'message'
]);
}
}
}
tests/Doctrine/Tests/DBAL/Functional/BlobTest.php
View file @
70340133
...
...
@@ -2,6 +2,7 @@
namespace
Doctrine\Tests\DBAL\Functional
;
use
Doctrine\DBAL\Driver\OCI8\Driver
as
OCI8Driver
;
use
Doctrine\DBAL\Driver\PDOSqlsrv\Driver
as
PDOSQLSrvDriver
;
use
Doctrine\DBAL\FetchMode
;
use
Doctrine\DBAL\ParameterType
;
...
...
@@ -10,7 +11,6 @@ use Doctrine\DBAL\Schema\Table;
use
Doctrine\DBAL\Types\Type
;
use
Doctrine\Tests\DbalFunctionalTestCase
;
use
function
fopen
;
use
function
in_array
;
use
function
str_repeat
;
use
function
stream_get_contents
;
...
...
@@ -55,10 +55,9 @@ class BlobTest extends DbalFunctionalTestCase
public
function
testInsertProcessesStream
()
{
if
(
in_array
(
$this
->
connection
->
getDatabasePlatform
()
->
getName
(),
[
'oracle'
,
'db2'
],
true
))
{
// https://github.com/doctrine/dbal/issues/3288 for DB2
// https://github.com/doctrine/dbal/issues/3290 for Oracle
$this
->
markTestIncomplete
(
'Platform does not support stream resources as parameters'
);
// https://github.com/doctrine/dbal/issues/3290
if
(
$this
->
connection
->
getDriver
()
instanceof
OCI8Driver
)
{
$this
->
markTestIncomplete
(
'The oci8 driver does not support stream resources as parameters'
);
}
$longBlob
=
str_repeat
(
'x'
,
4
*
8192
);
// send 4 chunks
...
...
@@ -112,10 +111,9 @@ class BlobTest extends DbalFunctionalTestCase
public
function
testUpdateProcessesStream
()
{
if
(
in_array
(
$this
->
connection
->
getDatabasePlatform
()
->
getName
(),
[
'oracle'
,
'db2'
],
true
))
{
// https://github.com/doctrine/dbal/issues/3288 for DB2
// https://github.com/doctrine/dbal/issues/3290 for Oracle
$this
->
markTestIncomplete
(
'Platform does not support stream resources as parameters'
);
// https://github.com/doctrine/dbal/issues/3290
if
(
$this
->
connection
->
getDriver
()
instanceof
OCI8Driver
)
{
$this
->
markTestIncomplete
(
'The oci8 driver does not support stream resources as parameters'
);
}
$this
->
connection
->
insert
(
'blob_table'
,
[
...
...
@@ -141,10 +139,8 @@ class BlobTest extends DbalFunctionalTestCase
public
function
testBindParamProcessesStream
()
{
if
(
in_array
(
$this
->
connection
->
getDatabasePlatform
()
->
getName
(),
[
'oracle'
,
'db2'
],
true
))
{
// https://github.com/doctrine/dbal/issues/3288 for DB2
// https://github.com/doctrine/dbal/issues/3290 for Oracle
$this
->
markTestIncomplete
(
'Platform does not support stream resources as parameters'
);
if
(
$this
->
connection
->
getDriver
()
instanceof
OCI8Driver
)
{
$this
->
markTestIncomplete
(
'The oci8 driver does not support stream resources as parameters'
);
}
$stmt
=
$this
->
connection
->
prepare
(
"INSERT INTO blob_table(id, clobfield, blobfield) VALUES (1, 'ignored', ?)"
);
...
...
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