PHP / PostgreSQL: запись двоичных данных с подготовленными операторами

Я долгое время пользовался pg_prepare() и pg_execute() , но теперь, когда я пишу ему двоичные данные, я столкнулся с трудностями.

Я с удивлением узнал, что session_encode() возвращает значения NULL в своих строках, но им всегда говорили, что вам не нужно избегать данных в подготовленных операциях. Так почему, когда я пишу поле 5kb в db, он обрезается примерно через 100 байт?

Если я выполню:

 UPDATE "solution_ubasket_temp" SET ("session_id", "session", "id") = ($1, $2, $3) WHERE "id"=$4" 

и установите второй член входного массива в возвращаемое значение 5kb session_encode() , он отключается после первого найденного значения NULL.

 select octet_length(session), * from solution_ubasket_temp 

подтверждает, что в «сеансе» хранится всего 105 байт, которые:

return_url | s: 30: " https: // solution-locale / Moneys "; complete | s: 0: ""; корзина | O: 15: "SolutionUBasket": 22: {s: 13:

bin2hex() подтверждает, что следующий байт после этой строки является NULL.

Создание «сеанса» text или bytea не имеет значения.

Я попробовал Googling для таких вещей, как «php postgresql подготовил операторы двоичные», но я просто получил множество обращений о MySQL и http://www.postgresqltutorial.com/postgresql-php/postgresql-blob/, но это использует что-то, называемое «PDO», и я не знаю, что это.

http://php.net/manual/en/function.pg-execute.php не имеет этого текста, но из http://php.net/manual/en/function.pg-query-params.php :

Значения, предназначенные для полей bytea, не поддерживаются в качестве параметров. Вместо этого используйте pg_escape_bytea () или используйте большие функции объекта.

может дать подсказку. Возможно, я должен использовать bytea вместо text и вызывать pg_escape_bytea() .

Таблица, в которой я работаю:

 CREATE TABLE solution_ubasket_temp ( session_id character varying(40) NOT NULL, session text, last_update timestamp with time zone NOT NULL DEFAULT now(), order_id integer, status character varying(2), email character varying(100), id integer NOT NULL DEFAULT nextval('solution_ubasket_temp_id_seq1'::regclass), CONSTRAINT solution_ubasket_temp_id_pk PRIMARY KEY (id) ) WITH ( OIDS=FALSE ); CREATE INDEX solution_ubasket_temp_email_index ON solution_ubasket_temp USING btree (email COLLATE pg_catalog."default"); CREATE INDEX solution_ubasket_temp_session_id_index ON solution_ubasket_temp USING btree (session_id COLLATE pg_catalog."default"); 

Я запускаю PHP 5.6 на Debian 8.5 и PostgreSQL 9.4.

Использование PDO

Чтобы эффективно вставлять / обновлять текст или бинарные данные в вашей таблице, вам нужно использовать PDO, это то, что может выглядеть код.

 <?php $dbh = new PDO('pgsql:host=localhost;dbname=test_rideshare', "postgres"); $fdata = file_get_contents('/tmp/sample.txt'); $n = 11; $stmt = $dbh->prepare("INSERT INTO solution_ubasket_temp(session_id,session,order_id) Values(?,?,?) "); $stmt->bindParam(1,$n); $stmt->bindParam(2,$fdata, PDO::PARAM_LOB); $stmt->bindParam(3,$n); $stmt->execute(); print $stmt->debugDumpParams(); print_r($stmt->errorInfo()); print_r($dbh->errorInfo()); $stmt = $dbh->prepare("SELECT session FROM solution_ubasket_temp LIMIT 1"); $stmt->execute(); $a = $stmt->fetch(); print_r($a); file_put_contents("/tmp/sample2.txt",$a['session']); ?> 

В приведенном выше примере кода показано, как сделать вставку, а затем снова прочитать данные. Он также записывает одни и те же данные в другой файл для сравнения. Сравнение с Visual или diff показывает, что они одинаковы.

Для обновления просто замените инструкцию insert оператором обновления

Двоичные данные

Если вы храните двоичные данные, вы должны использовать двоичное поле. То есть

 session bytea, 

На самом деле, я никогда не использую текстовые поля, когда когда-либо мне нужно хранить большие объекты, я выбираю двоичный файл, и, когда это возможно, я стараюсь избегать хранения больших объектов в db. На самом деле, хотя мой код выше показывает, как хранить файл в БД. это то, чего я никогда не буду делать на производстве.

PHP Serialize vs JSON

Ваши данные выглядят так, как будто это сериализованный PHP. Могу ли я предложить вместо этого переключиться на JSON и вместо этого сохранить данные в поле JSONB ? Это даст вам больше возможностей, чем сериализацию и десериализацию PHP, не говоря уже о том, что упоминание о том, что JSON поддерживается практически на любом языке программирования, при использовании сериализации PHP блокирует вас до PHP.