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

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

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

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

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

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

select octet_length(session), * from solution_ubasket_temp

подтверждает, что в сеансе хранится только 105 байтов:

RETURN_URL | s: 30:»https: // решение-локали / денежные суммы«; В комплекте с |: 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:

Значения, предназначенные для полей байтов, не поддерживаются в качестве параметров. Вместо этого используйте 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.

-1

Решение

Использование 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']);

?>

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

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

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

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

session bytea,

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

Сериализация PHP против JSON

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

1

Другие решения

Других решений пока нет …