简体   繁体   English

在C中使用Postgresql插入整数数组(libpq)

[英]Inserting integer array with postgresql in C (libpq)

I'm trying to post an integer array into my postgresql database. 我正在尝试将整数数组发布到我的postgresql数据库中。 I'm aware that I could format everything as a string and then send that string as one SQL command. 我知道我可以将所有内容格式化为字符串,然后将该字符串作为一个SQL命令发送。 However, I believe the PQexecParams function should also bring some help. 但是,我相信PQexecParams函数也应该带来一些帮助。 However, I'm kind of lost as how to use it. 但是,我有点迷失了如何使用它。

    //we need to convert the number into network byte order
    int val1 = 131;
    int val2 = 2342;
    int val3[5] = { 0, 7, 15, 31, 63 };
    //set the values to use
    const char *values[3] = { (char *) &val1, (char *) &val2, (char *) val3 };
    //calculate the lengths of each of the values
    int lengths[3] = { sizeof(val1), sizeof(val2), sizeof(val3) * 5 };
    //state which parameters are binary
    int binary[3] = { 1, 1, 1 };

    PGresult *res = PQexecParams(conn, "INSERT INTO family VALUES($1::int4, $2::int4, $3::INTEGER[])", 3, //number of parameters
            NULL, //ignore the Oid field
            values, //values to substitute $1 and $2
            lengths, //the lengths, in bytes, of each of the parameter values
            binary, //whether the values are binary or not
            0); //we want the result in text format

Yes this is copied from some tutorial. 是的,这是从某些教程中复制的。 However this returns : 但是,这返回:

 ERROR:  invalid array flags

Using a conventional method does work: 使用常规方法确实可以:

PQexec(conn, "INSERT INTO family VALUES (2432, 31, '{0,1,2,3,4,5}')");

Inserts data just fine, and I can read it out fine as well. 可以很好地插入数据,我也可以读出数据。

Any help would be greatly appreciated! 任何帮助将不胜感激! :) :)

libpq 's PQexecParams can accept values in text or binary form. libpqPQexecParams可以接受文本或二进制形式的值。

For text values, you must sprintf the integer into a buffer that you put in your char** values array. 对于文本值,必须将整数sprintf放入放置在char** values数组中的缓冲区中。 This is usually how it's done. 通常是这样完成的。 You can use text format with query parameters, there is no particular reason to fall back to interpolating the parameters into the SQL string yourself. 您可以将文本格式与查询参数一起使用,没有特殊的原因可以自己回退将参数插值到SQL字符串中。

If you want to use binary mode transfers, you must instead ensure the integer is the correct size for the target field, is in network byte order, and that you have specified the type OID. 如果要使用二进制模式传输,则必须确保整数是目标字段的正确大小,网络字节顺序,并且已指定OID类型。 Use htonl (for uint32_t ) or htons (for uint16_t ) for that. 为此使用htonl (对于uint32_t )或htons (对于uint16_t )。 It's fine to cast away signedness since you're just re-ordering the bytes. 丢弃签名是很好的,因为您只是在对字节重新排序。

So: 所以:

  • You cannot ignore the OID field if you're planning to use binary transfer 如果您打算使用二进制传输, 则不能忽略OID字段
  • Use htonl , don't brew your own byte-order conversion 使用htonl ,不要酿造自己的字节顺序转换
  • Your values array construction is wrong. 您的values数组构造错误。 You're putting char** s into an array of char* and casting away the wrong type. 您正在将char**放入char*数组中,并丢弃错误的类型。 You want &val1[0] or (equivalent in most/all real-world C implementations, but not technically the same per the spec) just val1 , instead of (char*)&val1 您需要&val1[0]或(在大多数/所有实际C实现中等效,但在规格上在技术上并不相同)只是val1 ,而不是(char*)&val1
  • You cannot assume that the on-wire format of integer[] is the same as C's int32_t[] . 您不能假定integer[]的在线格式与C的int32_t[] You must pass the type OID INT4ARRAYOID (see include/catalog/pg_type.h or select oid from pg_type where typname = '_int4' - the internal type name of an array is _ in front of its base type) and must construct a PostgreSQL array value compatible with the typreceive function in pg_type for that type (which is array_recv ) if you intend to send in binary mode. 必须传递OID INT4ARRAYOID类型(请参阅include/catalog/pg_type.hselect oid from pg_type where typname = '_int4' include/catalog/pg_type.h select oid from pg_type where typname = '_int4'数组的内部类型名称在其基本类型前面是_ ),并且必须构造一个PostgreSQL数组值与兼容typreceive在功能pg_type的那种类型(这是array_recv )如果你打算以二进制方式发送。 In particular, binary-format arrays have a header . 特别是, 二进制格式的数组具有header You cannot just leave out the header. 您不能只忽略标题。

In other words, the code is broken in multiple exciting ways and cannot possibly work as written. 换句话说,该代码以多种令人兴奋的方式被破坏,并且可能无法按编写的方式工作。

Really, there is rarely any benefit in sending integers in binary mode . 实际上, 以二进制模式发送整数几乎没有任何好处 Sending in text-mode is often actually faster because it's often more compact on the wire (small values). 实际上,以文本模式发送通常更快,因为它通常在线路上更紧凑(较小的值)。 If you're going to use binary mode, you will need to understand how C represents integers, how network vs host byte order works, etc. 如果要使用二进制模式,则需要了解C如何表示整数,网络与主机字节顺序的工作方式等。

Especially when working with arrays, text format is easier. 尤其是在处理数组时,文本格式更容易。

libpq could make this a lot easier than it presently does by offering good array construct / deconstruct functions for both text and binary arrays. 通过为文本数组和二进制数组提供良好的数组构造/解构函数, libpq可以使此操作比现在容易得多。 Patches are, as always, welcome. 补丁一如既往地受欢迎。 Right now, 3rd party libraries like libpqtypes largely fill this role. 现在, 诸如libpqtypes类的第三方库在很大程度上扮演了这个角色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM