A big gotcha exists for Oracle users.
You have to save CLOB objects using PDO::PARAM_STR, not PDO::PARAM_LOB.
But you MUST send the 4th argument, usually strlen($subject) or you get a LONG error.
ΠΠ½ΠΎΠ³Π΄Π° Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ Ρ
ΡΠ°Π½ΠΈΡΡ Β«Π±ΠΎΠ»ΡΡΠΈΠ΅Β» ΠΏΠΎΡΡΠΈΠΈ Π΄Π°Π½Π½ΡΡ
Π² Π±Π°Π·Π΅.
Π§Π°ΡΡΠΎ ΠΏΠΎΠ΄ Π±ΠΎΠ»ΡΡΠΈΠΌ ΠΏΠΎΠ½ΠΈΠΌΠ°ΡΡ ΠΎΠ±ΡΠ΅ΠΌ Π΄Π°Π½Π½ΡΡ
Β«ΠΎΠΊΠΎΠ»ΠΎ 4 ΠΊΠΈΠ»ΠΎΠ±Π°ΠΉΡΠΎΠ² ΠΈΠ»ΠΈ Π±ΠΎΠ»ΡΡΠ΅Β»,
Ρ
ΠΎΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
ΡΠΏΠΎΠΊΠΎΠΉΠ½ΠΎ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ Π΄ΠΎ 32 ΠΊΠΈΠ»ΠΎΠ±Π°ΠΉΡΠΎΠ², ΠΏΡΠ΅ΠΆΠ΄Π΅ ΡΠ΅ΠΌ
ΡΠ°Π·ΠΌΠ΅Ρ Π΄Π°Π½Π½ΡΡ
ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡ Β«Π±ΠΎΠ»ΡΡΠΈΠΌΒ». ΠΠΎΠ»ΡΡΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ (Π°Π½Π³Π». Large Objects, LOB) Π±ΡΠ²Π°ΡΡ
ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠΌΠΈ ΠΈΠ»ΠΈ Π΄Π²ΠΎΠΈΡΠ½ΡΠΌΠΈ. ΠΠΎΠ΄ΡΠ»Ρ PDO ΡΠ°Π·ΡΠ΅ΡΠ°Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΡΠ°ΠΊΠΈΠΌΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌΠΈ ΠΏΡΡΡΠΌ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ
ΡΠΈΠΏΠ° Π΄Π°Π½Π½ΡΡ
PDO::PARAM_LOB Π² ΠΌΠ΅ΡΠΎΠ΄Π°Ρ
PDOStatement::bindParam()
ΠΈΠ»ΠΈ PDOStatement::bindColumn().
Π€Π»Π°Π³ PDO::PARAM_LOB ΡΠΎΠΎΠ±ΡΠ°Π΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡΡ PDO, ΡΡΠΎ Π΄Π°Π½Π½ΡΠ΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ
ΠΎΡΠΎΠ±ΡΠ°Π·ΠΈΡΡ Π² Π²ΠΈΠ΄Π΅ ΠΏΠΎΡΠΎΠΊΠ°, ΡΡΠΎΠ±Ρ ΡΠΏΡΠ°Π²Π»ΡΡΡ Π΄Π°Π½Π½ΡΠΌΠΈ
ΡΠ΅ΡΠ΅Π· API-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ PHP-ΠΏΠΎΡΠΎΠΊΠΎΠ².
ΠΡΠΈΠΌΠ΅Ρ #1 ΠΡΠ²ΠΎΠ΄ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ, ΠΊΠΎΡΠΎΡΠΎΠ΅ Ρ ΡΠ°Π½ΠΈΡΡΡ Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½ΡΡ
Π ΠΏΡΠΈΠΌΠ΅ΡΠ΅ LOB-ΠΎΠ±ΡΠ΅ΠΊΡ ΡΠ²ΡΠ·ΡΠ²Π°ΡΡ Ρ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ $lob, Π° Π·Π°ΡΠ΅ΠΌ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ Π² Π±ΡΠ°ΡΠ·Π΅Ρ ΡΡΠ½ΠΊΡΠΈΠ΅ΠΉ fpassthru(). ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ PDO-ΠΎΠ±ΡΠ΅ΠΊΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΠ» LOB-ΠΎΠ±ΡΠ΅ΠΊΡ ΠΊΠ°ΠΊ ΠΏΠΎΡΠΎΠΊ, Ρ Π±ΠΎΠ»ΡΡΠΈΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ ΠΏΠΎΠ»ΡΡΠΈΡΡΡ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΡΠ½ΠΊΡΠΈΡΠΌΠΈ Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ fgets(), fread() ΠΈ stream_get_contents().
<?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
header("Content-Type: $type");
fpassthru($lob);
?>
ΠΡΠΈΠΌΠ΅Ρ #2 ΠΡΡΠ°Π²ΠΊΠ° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π² Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
Π‘Π»Π΅Π΄ΡΡΡΠΈΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΠΎΡΠΊΡΡΠ²Π°Π΅Ρ ΡΠ°ΠΉΠ» ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π΄Π΅ΡΠΊΡΠΈΠΏΡΠΎΡ ΡΠ°ΠΉΠ»Π° Π² ΠΎΠ±ΡΠ΅ΠΊΡ PDO Π΄Π»Ρ Π²ΡΡΠ°Π²ΠΊΠΈ ΡΠ°ΠΉΠ»Π° Π² Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ Π² Π²ΠΈΠ΄Π΅ LOB-ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΠ±ΡΠ΅ΠΊΡ PDO ΠΈΠ·Π²Π»Π΅ΡΡΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ ΡΠ°ΠΉΠ»Π° ΠΈ Π²ΡΡΠ°Π²ΠΈΡ Π΅Π³ΠΎ Π² Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ ΡΠ°ΠΌΡΠΌ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΡΠΌ ΡΠΏΠΎΡΠΎΠ±ΠΎΠΌ.
<?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("insert into images (id, contenttype, imagedata) values (?, ?, ?)");
$id = get_new_id(); // ΠΠ΅ΠΊΠΎΡΠΎΡΠ°Ρ ΡΡΠ½ΠΊΡΠΈΡ, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΠ΄Π΅Π»ΠΈΡ Π½ΠΎΠ²ΡΠΉ ID
// ΠΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΡΡΠΎ Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌΡΡ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΡΠ°ΠΉΠ»ΠΎΠ² Π½Π° ΡΠ΄Π°Π»ΡΠ½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ
$fp = fopen($_FILES['file']['tmp_name'], 'rb');
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $_FILES['file']['type']);
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);
$db->beginTransaction();
$stmt->execute();
$db->commit();
?>
ΠΡΠΈΠΌΠ΅Ρ #3 ΠΡΡΠ°Π²ΠΊΠ° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π² Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ : Oracle
ΠΠ Oracle ΡΡΠ΅Π±ΡΠ΅Ρ Π΄ΡΡΠ³ΠΎΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ Π΄Π»Ρ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ³ΠΎ ΡΠ°ΠΉΠ»Π° Π² Π²ΠΈΠ΄Π΅ LOB-ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΈ Π²ΡΡΠ°Π²ΠΊΠΈ Π±ΠΎΠ»ΡΡΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π² Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ . ΠΡΡΠ°Π²ΠΊΡ Π±ΠΎΠ»ΡΡΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π² ΠΠ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ Π² ΡΠ°ΠΌΠΊΠ°Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ, ΠΈΠ½Π°ΡΠ΅ ΠΠ Π·Π°ΡΠΈΠΊΡΠΈΡΡΠ΅Ρ LOB-ΠΎΠ±ΡΠ΅ΠΊΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎ Π²ΡΡΠ°Π²ΠΈΠ»Π°, Ρ Π½ΡΠ»Π΅Π²ΠΎΠΉ Π΄Π»ΠΈΠ½ΠΎΠΉ β ΠΊΠ°ΠΊ ΡΠ°ΡΡΡ Π½Π΅ΡΠ²Π½ΠΎΠΉ ΡΠΈΠΊΡΠ°ΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ°.
<?php
$db = new PDO('oci:', 'scott', 'tiger');
$stmt = $db->prepare("insert into images (id, contenttype, imagedata) " .
"VALUES (?, ?, EMPTY_BLOB()) RETURNING imagedata INTO ?")
;
$id = get_new_id(); // ΠΠ΅ΠΊΠΎΡΠΎΡΠ°Ρ ΡΡΠ½ΠΊΡΠΈΡ, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΠ΄Π΅Π»ΠΈΡ Π½ΠΎΠ²ΡΠΉ ID
// ΠΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΡΡΠΎ Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌΡΡ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΡΠ°ΠΉΠ»ΠΎΠ² Π½Π° ΡΠ΄Π°Π»ΡΠ½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ
$fp = fopen($_FILES['file']['tmp_name'], 'rb');
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $_FILES['file']['type']);
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);
$db->beginTransaction();
$stmt->execute();
$db->commit();
?>A big gotcha exists for Oracle users.
You have to save CLOB objects using PDO::PARAM_STR, not PDO::PARAM_LOB.
But you MUST send the 4th argument, usually strlen($subject) or you get a LONG error.PDOStatement's methods bindParam and bindValue also work with strings, as in:
<?php
$data = file_get_contents($filename);
$stmt->bindValue(1, $data, PDO::PARAM_LOB);
//...
?>
This was the only way I could make it work with PostgreSQL.There seems to be a bug that affects example 1 above. PDO::PARAM_LOB when used with pdo::bindColumn() is supposed to return a stream but it returns a string. Passing this string to fpassthru() then triggers an error with the message 'supplied argument is not a valid stream resource'. This has been reported in bug #40913. The work around is to do the following:
<?php
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
header("Content-Type: $type");
echo($lob);
?>
Since the browser is expecting an image after the call to header() writing the string representation of the binary output with echo() has the same affect as calling fpassthru().I spend a lot of time trying to get this to work, but no matter what I did PDO corrupted my data.
I finally discovered that I had been using:
$pdo->exec('SET CHARACTER SET utf8');
in the TRY part of my connection script.
This off course doesn't work when you feed binary input to PDO using the parameter lob.For selecting data out of Postgres, the data type of the column in the table determined if the parameter bound with PARAM_LOB returned a string or returned a resource.
<?php
// create table log ( data text ) ;
$geth = $dbh->prepare('select data from log ');
$geth->execute();
$geth->bindColumn(1, $dataString, PDO::PARAM_LOB);
$geth->fetch(PDO::FETCH_BOUND);
echo ($dataString); // $dataString is a string
// create table log ( data bytea ) ;
$geth = $dbh->prepare('select data from log');
$geth->execute();
$geth->bindColumn(1, $dataFH, PDO::PARAM_LOB);
$geth->fetch(PDO::FETCH_BOUND);
fpassthru($dataFH); // $dataFH is a resourceThe DBMSs that are listed above have these (default) limits on the maximum size of a char string. The maximum is given in bytes so the number of characters storable can be smaller if a multibyte encoding is used.
CUBRID: 16kB
SQL Server: 2GB
Firebird: 32kB
IBM Db2: 32kB
Informix: 32kB
MySQL: 16kB
Oracle: 2kB
PostgreSQL: 1GB
SQLite: 1 billion bytes
4D: Unknown, but LOBs are limited to 2GB.