简体   繁体   English

pqxx 和 null 外键

[英]pqxx and null foreign keys

I have the following code:我有以下代码:

void DB_Series_Base::doInsert(pqxx::connection &conn, Series &obj) {
    pqxx::work work {conn};
    string sql { string{"INSERT INTO series ("} + INSERT_LIST + ") VALUES ($1, $2) RETURNING id" };
    pqxx::result results = work.exec_params(sql,
        obj.getName().length() > 0 ? obj.getName().c_str() : nullptr,
        obj.getUniverseId() != 0 ? obj.getUniverseId(): nullptr);
    work.commit();
    obj.setId(results[0][0].as<int>());
}

This does not compile with the error 'non-pointer operand type 'int' incompatible with nullptr'.这不会与错误'非指针操作数类型'int'与nullptr不兼容'编译。 Okay, I get it.好的,我明白了。 The trinary operator needs to return a value with a consistent datatype.三元运算符需要返回具有一致数据类型的值。

In this place, universeId is a foreign key into the Universe table.在这个地方,universeId 是 Universe 表的外键。

I tried this:我试过这个:

void DB_Series_Base::doInsert(pqxx::connection &conn, Series &obj) {
    int universeId = obj.getUniverseId();

    pqxx::work work {conn};
    string sql { string{"INSERT INTO series ("} + INSERT_LIST + ") VALUES ($1, $2) RETURNING id" };
    pqxx::result results = work.exec_params(sql,
        obj.getName().length() > 0 ? obj.getName().c_str() : nullptr,
        &universeId);
    work.commit();
    obj.setId(results[0][0].as<int>());
}

But this generates link errors (which I don't usually have):但这会产生链接错误(我通常没有):

Undefined symbols for architecture x86_64:
  "pqxx::string_traits<int*>::size_buffer(int* const&)", referenced from:
      unsigned long pqxx::size_buffer<int*>(int* const&) in libauthor-mac.a(DB_Series_Base.o)
  "pqxx::string_traits<int*>::into_buf(char*, char*, int* const&)", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > pqxx::to_string<int*>(int* const&) in libauthor-mac.a(DB_Series_Base.o)
  "pqxx::nullness<int*, void>::is_null(int* const&)", referenced from:
      bool pqxx::is_null<int*>(int* const&) in libauthor-mac.a(DB_Series_Base.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:39: AuthorServer] Error 1```

The only other thing I can think of is to entirely build custom SQL for each insert / update, and embed "NULL" in the VALUES section instead of $2 etc. That's kind of gross, but I can do it if no one has a better suggestion.

So... how can I pass either the actual foreign key (universeId) -or- nullptr as apprpriate?




Oh, this is cool.哦,这很酷。 I discovered the nullif function.我发现了nullif function。

void
TestDatabase::testNullForeignKeys() {
    connect();
    string sqlSeries { "INSERT INTO series(name, universe_id) VALUES ($1, nullif($2, 0)) RETURNING id" };

    int universeId = 0;

    pqxx::work populateSeries {*connection};
    pqxx::result results = populateSeries.exec_params(sqlSeries, "Test Series", universeId);
    populateSeries.commit();
}

Notice the nullif($2,0) in the VALUES portion of the INSERT statement.请注意 INSERT 语句的 VALUES 部分中的nullif($2,0) What this says:这说明了什么:

If the first argument == the second one, return null.如果第一个参数 == 第二个参数,则返回 null。 Otherwise return the first argument.否则返回第一个参数。 So if universeId is 0, nullif returns NULL.因此,如果 UniverseId 为 0,则 nullif 返回 NULL。 Otherwise it returns the real value.否则返回真实值。

This solves my problem.这解决了我的问题。

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

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