PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Chèn số dấu phẩy động vào bảng bằng libpq

Có hai lỗi trong mã của bạn:

  • Bạn đang cố gắng gửi dữ liệu nhị phân, nhưng bạn không cho PQexecParams biết đó là loại nào.

    Điều đó không thể hoạt động. Thiếu thông tin về loại, PostgreSQL sẽ sử dụng loại unknown và coi nó như một chuỗi. Điều đó có nghĩa là biểu diễn nhị phân của bạn sẽ được cung cấp cho float8in hàm chuyển đổi các chuỗi thành các giá trị chính xác gấp đôi, điều này sẽ thất bại khủng khiếp. Đây có thể là những gì bạn đang quan sát.

    Bạn sẽ phải sử dụng tham số thứ tư với Oid[] chứa 701 (hoặc FLOAT8OID nếu bạn muốn sử dụng #define của PostgreSQL , nhưng bạn phải #include <postgres.h><catalog/pg_type.h> cho điều đó).

  • Bạn nhầm tưởng rằng biểu diễn nhị phân của PostgreSQL về double precision type là định dạng nhị phân cho double đang được sử dụng trên máy khách của bạn.

    Điều này có thể vô tình hoạt động nếu chương trình của bạn đang chạy trên big-endian máy, vì hầu như mọi kiến ​​trúc ngày nay đều sử dụng số dấu chấm động IEEE .

    Nếu bạn đọc mã nguồn, bạn sẽ thấy rằng định dạng nhị phân over-the-wire của PostgreSQL được xác định trong pq_sendfloat8 trong src/backend/libpq/pqformat.c , gọi pq_sendint64 , chuyển đổi giá trị 8 byte thành thứ tự byte mạng (giống như biểu diễn big-endian).

Vì vậy, bạn phải xác định một hàm chuyển đổi tương tự như sau:

static void to_nbo(double in, double *out) {
    uint64_t *i = (uint64_t *)&in;
    uint32_t *r = (uint32_t *)out;

    /* convert input to network byte order */
    r[0] = htonl((uint32_t)((*i) >> 32));
    r[1] = htonl((uint32_t)*i);
}

Sau đó, mã của bạn có thể trông giống như sau:

Oid types[1];
double converted;

...

types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;

Nhưng thẳng thắn mà nói, sẽ dễ dàng hơn nhiều khi sử dụng biểu diễn văn bản. Điều đó sẽ làm cho mã của bạn độc lập với nội bộ PostgreSQL và có lẽ không chậm hơn nhiều.

Nó không giống như vậy, nhưng nếu double precision giá trị được lấy từ bảng PostgreSQL ở một nơi khác, bạn có thể đặt extra_float_digits = 3 để bạn được đảm bảo không bị mất bất kỳ độ chính xác nào khi các giá trị được chuyển đổi thành biểu diễn chuỗi của chúng ..




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 2ndQuadrant tại PostgresConf US 2018

  2. Ngủ đông không lưu Đối tượng trong Cơ sở dữ liệu?

  3. Làm cách nào để bảo vệ khỏi việc đưa vào SQL khi mệnh đề WHERE được tạo động từ biểu mẫu tìm kiếm?

  4. Hội nghị PostgreSQL mùa xuân 2011, Hoa Kỳ / Canada

  5. PL / Perl gửi thư trong Postgresql