Байт-столбец Postgres возвращает строку (массив символов) вместо байтового массива. - PullRequest
4 голосов
/ 22 августа 2011

Я использую C # для написания конкретной реализации провайдера для нашего продукта для разных баз данных.Если не вдаваться в детали, один из столбцов имеет тип байтового массива (bytea в postgres - из-за предпочтений bytea был выбран вместо BLOB-объекта).Единственная проблема заключается в том, что он не возвращает то же значение, которое было вставлено.Когда я вставляю Int32 («0»), я получаю 8 [92 и 8x 48] (вместо [0,0,0,0]).Мне нужно решение с точки зрения производительности, которое будет возвращать чистые байты, которые я вставил, вместо представления ASCII значения «0» на 8 байтов.

Я использую Npgsql для извлечения данных.Если кто-то знает решение для c #, я буду рад узнать и его.

Редактировать: Postgres 9.0, .Net 3.5

Упрощение

Командазапрос: - внутри него только вставка вставки

select InsertOrUpdateEntry(:nodeId, :timeStamp, :data)

Параметр данных:

byte [] value = BitConverter.GetBytes((int)someValue);

Параметр назначается, как показано ниже

command.Parameters.Add(new NpgsqlParameter("data", NpgsqlDbType.Bytea) 
{ Value = value });

Выбор статистики:

select * from Entries

Тот же массив байтов, который я ввел, я хочу вернуться.Буду очень признателен за вашу помощь.

Вход: 0 0 0 0Выход по току: 92 48 48 48 48 48 48 48 48Ожидаемый результат: 0 0 0 0

Ответы [ 2 ]

5 голосов
/ 23 августа 2011

В Npgsql есть класс NpgsqlDataReader для извлечения вставленных строк, например:

NpgsqlConnection conn = new NpgsqlConnection(connStr);
conn.Open();

NpgsqlCommand insertCmd =
    new NpgsqlCommand("INSERT INTO binaryData (data) VALUES(:dataParam)", conn);
NpgsqlParameter param = new NpgsqlParameter("dataParam", NpgsqlDbType.Bytea);

byte[] inputBytes = BitConverter.GetBytes((int)0);
Console.Write("Input:");
foreach (byte b in inputBytes)
    Console.Write(" {0}", b);
Console.WriteLine();

param.Value = inputBytes;
insertCmd.Parameters.Add(param);
insertCmd.ExecuteNonQuery();

NpgsqlCommand selectCmd = new NpgsqlCommand("SELECT data FROM binaryData", conn);
NpgsqlDataReader dr = selectCmd.ExecuteReader();
if(dr.Read())
{
    Console.Write("Output:");
    byte[] result = (byte[])dr[0];
    foreach(byte b in result)
        Console.Write(" {0}", b);
    Console.WriteLine();
}

conn.Close();

Результат из приложения C #:

Input: 0 0 0 0
Output: 0 0 0 0

Результат из pgAdmin:

"\000\000\000\000"

РЕДАКТИРОВАТЬ:

Я нашел объяснение, почему вы получаете:

92 48 48 48 48 48 48 48 48

Я проверил свой код с предыдущая версия Npgsql2.0.10-bin-ms.net3.5sp1.zip и получите результат выше (конечно, pgAdmin возвращает \000\000\000\000), поэтому я думаю, что лучше всего использовать другую версию без этой ошибки.

ОТВЕТ: Пользовательская версия Npgsql выше, чем 2.0.10

3 голосов
/ 17 июня 2013

Запущена та же проблема, но удалось решить проблему, не прибегая к смене драйверов.

Документация PHP содержит хорошее описание того, что происходит, Postgres возвращает экранированные данные. Проверьте свои выходные данные по ASCII-таблице , когда вы видите 92 48 ... это текст, приводящий к восьмеричной escape-последовательности \0xx, как описывает PHP.

Бинарный тип данных Postgres объясняет выходные октеты . Не беспокойтесь, есть примеры кода .

Решение состоит в том, чтобы сообщить Postgres, как экранировать байты, которые могут быть либо escape, либо hex. В этом случае введите следующее в Postgres через psql, чтобы сопоставить ваши данные:

ALTER DATABASE yourdb SET BYTEA_OUTPUT TO 'escape';
...