команда копирования postgres, двоичный файл - PullRequest
3 голосов
/ 14 июня 2011

Я использую COPY для копирования поля из таблицы в файл. это поле представляет собой сжатый текстовый файл, поэтому я использую двоичную копию. файл создан, единственная проблема в том, что COPY добавляет к файлу заголовок и трейлер (?), который мне не нужен. это можно изменить? есть ли параметр, который может заставить COPY поставить поле в точности так, как оно есть в базе данных?

Если я вручную удаляю нежелательный заголовок, я могу извлечь файл с помощью zcat или gunzip.

Я делаю что-то вроде этого:

psql -d some_database -c \
 "copy  (select some_column from a_table where id=900) to stdout with BINARY;" > /tmp/tmp.gz

А потом я хочу сделать

gunzip /tmp/tmp.gz

Есть идеи?

Ответы [ 6 ]

3 голосов
/ 14 июня 2011

Одна возможность, которая работает, хотя она вам может не понравиться:

psql -At -c "select encode(content, 'base64') from t where ..."  | base64 -d

т.е. распечатайте содержимое как base64 и расшифруйте его. Я думаю, что реальность такова, что psql предназначен для создания читабельного вывода, и убедить его в искажении необработанных двоичных данных намеренно сложно.

Полагаю, если вам этого хватит, вы можете написать какой-нибудь инструмент (скрипт на Perl / python) для подключения к базе данных и прямой печати необработанного вывода.

Опция WITH WITH BINARY для COPY не просто выполняет простой двоичный вывод, она выполняет некоторое кодирование, на которое, вероятно, сомнительно полагаться.

1 голос
/ 14 июня 2011

Я не знаю простого способа ... COPY имеет двоичный формат с заголовком переменной длины, который не очень легко "обрезать".Помимо этого, PG довольно текстоцентричен, я не думаю, что есть способ форсировать «сырой» (двоичный) вывод из SELECT для поля BYTEA.

Вы можете получить текстовый шестнадцатеричный вывод инапишите себе небольшую программу (C, Perl или что-то еще), чтобы преобразовать ее из скажем \x000102414243 в двоичный файл.Не сложно, но не так просто (и шестнадцатеричный формат в Postgresql 9.0)

psql  -t -q -c "select binaryfield from.. where ..." mydb  |  myhextobin > tmp.gz

Кстати, ответ Гжегожа очень уместен.

Добавлено: не очень чисто и не защищено от ошибокчто-то находит это полезным ...

/* expects a pg hexadecimal string, in "\x....." format, and converts to binary*/
/* warning: no checks! it just ignores chars outside [0-9a-f] */
#include<stdio.h>
int main() {
    int x, pos, v;
    char hex[3]={0,0,0};
    pos = 0;
    while( (x = getchar()) >= 0) {
        if(( x >='0' && x <= '9') || ( x >= 'a' && x <= 'f' )) {
            hex[pos++] = (char)x;
            if(pos == 2) {
                sscanf(hex, "%x", &v);
                putchar((char)v);
                pos = 0;
            }
        }
    }
    return pos==0 ? 0 : 1;
}
1 голос
/ 14 июня 2011

Вы уверены, что это лучший способ сохранить сжатый текст в базе данных как двоичный файл? Согласно документации длинный текст неявно / автоматически сжимается:

длинные строки сжимаются система автоматически, поэтому физическая требование на диске может быть меньше. Очень длинные значения также хранятся в фоновые таблицы, чтобы они не мешать быстрый доступ к короче значения столбца. В любом случае максимально длинная строка символов, может храниться около 1 ГБ.

0 голосов
/ 23 сентября 2013

Команда копирования выполняет эту работу. Вам нужно только сказать: --no-align и --tuples-only.

Для сжатия используйте gzip между psql и файлом

psql --tuples-only --no-align -d some_database -c \ "copy (select some_column from a_table where id=900) to stdout with BINARY;" | gzip > /tmp/tmp.gz

0 голосов
/ 15 июня 2011

Вам может быть проще сделать это, используя язык с драйверами клиента и способностью читать тип байта: PHP, python, ruby, perl, javascript, java и т. Д. Просто выполните свой запрос там, используйте gzipбиблиотеки, которые, вероятно, уже существуют на этом языке, и запишите файл.

Кроме того, вы можете использовать процедурный язык внутри базы данных и создать хранимую процедуру.Вы передадите запрошенное имя файла в хранимую процедуру.

0 голосов
/ 14 июня 2011

Не рекомендуется пытаться декодировать двоичный формат postgresql.Тот факт, что используемый вами тестовый файл работает, не означает, что все будет работать.Например, возможно, некоторые последовательности символов (не фигурирующие в вашем тестовом файле) экранируются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...