bool v_has_node(uint32_t parentId, uint32_t childId) { if (parentId == 0) return false; if (parentId == childId) return true; PostgresStrings<2> parms; parms.set(0, parentId); parms.set(1, childId); check_postgres(); PGresult* result = PQexecParams(s_postgres, "SELECT vault.has_node($1, $2)", 2, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres SELECT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return false; } DS_DASSERT(PQntuples(result) == 1); bool retval = (*PQgetvalue(result, 0, 0) == 't'); PQclear(result); return retval != 0; }
void dm_send_state(GameHost_Private* host, GameClient_Private* client) { check_postgres(host); MOUL::NetMsgSDLState* state = MOUL::NetMsgSDLState::Create(); state->m_contentFlags = MOUL::NetMessage::e_HasTimeSent | MOUL::NetMessage::e_NeedsReliableSend; state->m_timestamp.setNow(); state->m_isInitial = true; state->m_persistOnServer = true; state->m_isAvatar = false; uint32_t states = 0; DS::Blob ageSdlBlob = host->m_ageSdlHook.toBlob(); if (ageSdlBlob.size()) { Game_AgeInfo info = s_ages[host->m_ageFilename]; state->m_object.m_location = MOUL::Location::Make(info.m_seqPrefix, -2, MOUL::Location::e_BuiltIn); state->m_object.m_name = "AgeSDLHook"; state->m_object.m_type = 1; // SceneObject state->m_object.m_id = 1; state->m_sdlBlob = ageSdlBlob; DM_WRITEMSG(host, state); DS::CryptSendBuffer(client->m_sock, client->m_crypt, host->m_buffer.buffer(), host->m_buffer.size()); ++states; } for (sdlstatemap_t::iterator state_iter = host->m_states.begin(); state_iter != host->m_states.end(); ++state_iter) { for (sdlnamemap_t::iterator it = state_iter->second.begin(); it != state_iter->second.end(); ++it) { state->m_object = state_iter->first; state->m_isAvatar = it->second.m_isAvatar; state->m_persistOnServer = it->second.m_persist; state->m_sdlBlob = it->second.m_state.toBlob(); DM_WRITEMSG(host, state); DS::CryptSendBuffer(client->m_sock, client->m_crypt, host->m_buffer.buffer(), host->m_buffer.size()); ++states; } } state->unref(); // Final message indicating the whole state was sent MOUL::NetMsgInitialAgeStateSent* reply = MOUL::NetMsgInitialAgeStateSent::Create(); reply->m_contentFlags = MOUL::NetMessage::e_HasTimeSent | MOUL::NetMessage::e_IsSystemMessage | MOUL::NetMessage::e_NeedsReliableSend; reply->m_timestamp.setNow(); reply->m_numStates = states; DM_WRITEMSG(host, reply); DS::CryptSendBuffer(client->m_sock, client->m_crypt, host->m_buffer.buffer(), host->m_buffer.size()); reply->unref(); }
void dm_save_sdl_state(GameHost_Private* host, const DS::String& descriptor, const MOUL::Uoid& object, const SDL::State& state) { check_postgres(host); DS::Blob sdlBlob = state.toBlob(); PostgresStrings<4> parms; host->m_buffer.truncate(); object.write(&host->m_buffer); parms.set(0, host->m_serverIdx); parms.set(1, descriptor); parms.set(2, DS::Base64Encode(host->m_buffer.buffer(), host->m_buffer.size())); parms.set(3, DS::Base64Encode(sdlBlob.buffer(), sdlBlob.size())); PGresult* result = PQexecParams(host->m_postgres, "SELECT idx FROM game.\"AgeStates\"" " WHERE \"ServerIdx\"=$1 AND \"Descriptor\"=$2 AND \"ObjectKey\"=$3", 3, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres SELECT error: %s\n", __FILE__, __LINE__, PQerrorMessage(host->m_postgres)); PQclear(result); return; } if (PQntuples(result) == 0) { PQclear(result); result = PQexecParams(host->m_postgres, "INSERT INTO game.\"AgeStates\"" " (\"ServerIdx\", \"Descriptor\", \"ObjectKey\", \"SdlBlob\")" " VALUES ($1, $2, $3, $4)", 4, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, "%s:%d:\n Postgres INSERT error: %s\n", __FILE__, __LINE__, PQerrorMessage(host->m_postgres)); PQclear(result); return; } PQclear(result); } else { DS_DASSERT(PQntuples(result) == 1); parms.set(0, DS::String(PQgetvalue(result, 0, 0))); parms.set(1, parms.m_strings[3]); // SDL blob PQclear(result); result = PQexecParams(host->m_postgres, "UPDATE game.\"AgeStates\"" " SET \"SdlBlob\"=$2 WHERE idx=$1", 2, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, "%s:%d:\n Postgres UPDATE error: %s\n", __FILE__, __LINE__, PQerrorMessage(host->m_postgres)); PQclear(result); return; } PQclear(result); } }
DS::Uuid gen_uuid() { check_postgres(); PGresult* result = PQexec(s_postgres, "SELECT uuid_generate_v4()"); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres SELECT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return DS::Uuid(); } DS_DASSERT(PQntuples(result) == 1); DS::Uuid uuid(PQgetvalue(result, 0, 0)); PQclear(result); return uuid; }
bool v_update_node(const DS::Vault::Node& node) { /* This should be plenty to store everything we need without a bunch * of dynamic reallocations */ PostgresStrings<32> parms; char fieldbuf[1024]; size_t parmcount = 1; char* fieldp = fieldbuf; #define SET_FIELD(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "\"" #name "\"=$%Zu,", parmcount); \ } int now = time(0); SET_FIELD(ModifyTime, now); if (node.has_CreateAgeName()) SET_FIELD(CreateAgeName, node.m_CreateAgeName); if (node.has_CreateAgeUuid()) SET_FIELD(CreateAgeUuid, node.m_CreateAgeUuid.toString()); if (node.has_CreatorUuid()) SET_FIELD(CreatorUuid, node.m_CreatorUuid.toString()); if (node.has_CreatorIdx()) SET_FIELD(CreatorIdx, node.m_CreatorIdx); if (node.has_NodeType()) SET_FIELD(NodeType, node.m_NodeType); if (node.has_Int32_1()) SET_FIELD(Int32_1, node.m_Int32_1); if (node.has_Int32_2()) SET_FIELD(Int32_2, node.m_Int32_2); if (node.has_Int32_3()) SET_FIELD(Int32_3, node.m_Int32_3); if (node.has_Int32_4()) SET_FIELD(Int32_4, node.m_Int32_4); if (node.has_Uint32_1()) SET_FIELD(Uint32_1, node.m_Uint32_1); if (node.has_Uint32_2()) SET_FIELD(Uint32_2, node.m_Uint32_2); if (node.has_Uint32_3()) SET_FIELD(Uint32_3, node.m_Uint32_3); if (node.has_Uint32_4()) SET_FIELD(Uint32_4, node.m_Uint32_4); if (node.has_Uuid_1()) SET_FIELD(Uuid_1, node.m_Uuid_1.toString()); if (node.has_Uuid_2()) SET_FIELD(Uuid_2, node.m_Uuid_2.toString()); if (node.has_Uuid_3()) SET_FIELD(Uuid_3, node.m_Uuid_3.toString()); if (node.has_Uuid_4()) SET_FIELD(Uuid_4, node.m_Uuid_4.toString()); if (node.has_String64_1()) SET_FIELD(String64_1, node.m_String64_1); if (node.has_String64_2()) SET_FIELD(String64_2, node.m_String64_2); if (node.has_String64_3()) SET_FIELD(String64_3, node.m_String64_3); if (node.has_String64_4()) SET_FIELD(String64_4, node.m_String64_4); if (node.has_String64_5()) SET_FIELD(String64_5, node.m_String64_5); if (node.has_String64_6()) SET_FIELD(String64_6, node.m_String64_6); if (node.has_IString64_1()) SET_FIELD(IString64_1, node.m_IString64_1); if (node.has_IString64_2()) SET_FIELD(IString64_2, node.m_IString64_2); if (node.has_Text_1()) SET_FIELD(Text_1, node.m_Text_1); if (node.has_Text_2()) SET_FIELD(Text_2, node.m_Text_2); if (node.has_Blob_1()) SET_FIELD(Blob_1, DS::Base64Encode(node.m_Blob_1.buffer(), node.m_Blob_1.size())); if (node.has_Blob_2()) SET_FIELD(Blob_2, DS::Base64Encode(node.m_Blob_2.buffer(), node.m_Blob_2.size())); #undef SET_FIELD DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 1) = 0; // Get rid of the last comma DS::String queryStr = "UPDATE vault.\"Nodes\"\n SET "; queryStr += fieldbuf; queryStr += "\n WHERE idx=$1"; parms.set(0, node.m_NodeIdx); check_postgres(); PGresult* result = PQexecParams(s_postgres, queryStr.c_str(), parmcount, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, "%s:%d:\n Postgres UPDATE error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return false; } PQclear(result); return true; }
uint32_t v_create_node(const DS::Vault::Node& node) { /* This should be plenty to store everything we need without a bunch * of dynamic reallocations */ PostgresStrings<31> parms; char fieldbuf[1024]; size_t parmcount = 0; char* fieldp = fieldbuf; #define SET_FIELD(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "\"" #name "\","); \ } int now = time(0); SET_FIELD(CreateTime, now); SET_FIELD(ModifyTime, now); if (node.has_CreateAgeName()) SET_FIELD(CreateAgeName, node.m_CreateAgeName); if (node.has_CreateAgeUuid()) SET_FIELD(CreateAgeUuid, node.m_CreateAgeUuid.toString()); if (node.has_CreatorUuid()) SET_FIELD(CreatorUuid, node.m_CreatorUuid.toString()); if (node.has_CreatorIdx()) SET_FIELD(CreatorIdx, node.m_CreatorIdx); if (node.has_NodeType()) SET_FIELD(NodeType, node.m_NodeType); if (node.has_Int32_1()) SET_FIELD(Int32_1, node.m_Int32_1); if (node.has_Int32_2()) SET_FIELD(Int32_2, node.m_Int32_2); if (node.has_Int32_3()) SET_FIELD(Int32_3, node.m_Int32_3); if (node.has_Int32_4()) SET_FIELD(Int32_4, node.m_Int32_4); if (node.has_Uint32_1()) SET_FIELD(Uint32_1, node.m_Uint32_1); if (node.has_Uint32_2()) SET_FIELD(Uint32_2, node.m_Uint32_2); if (node.has_Uint32_3()) SET_FIELD(Uint32_3, node.m_Uint32_3); if (node.has_Uint32_4()) SET_FIELD(Uint32_4, node.m_Uint32_4); if (node.has_Uuid_1()) SET_FIELD(Uuid_1, node.m_Uuid_1.toString()); if (node.has_Uuid_2()) SET_FIELD(Uuid_2, node.m_Uuid_2.toString()); if (node.has_Uuid_3()) SET_FIELD(Uuid_3, node.m_Uuid_3.toString()); if (node.has_Uuid_4()) SET_FIELD(Uuid_4, node.m_Uuid_4.toString()); if (node.has_String64_1()) SET_FIELD(String64_1, node.m_String64_1); if (node.has_String64_2()) SET_FIELD(String64_2, node.m_String64_2); if (node.has_String64_3()) SET_FIELD(String64_3, node.m_String64_3); if (node.has_String64_4()) SET_FIELD(String64_4, node.m_String64_4); if (node.has_String64_5()) SET_FIELD(String64_5, node.m_String64_5); if (node.has_String64_6()) SET_FIELD(String64_6, node.m_String64_6); if (node.has_IString64_1()) SET_FIELD(IString64_1, node.m_IString64_1); if (node.has_IString64_2()) SET_FIELD(IString64_2, node.m_IString64_2); if (node.has_Text_1()) SET_FIELD(Text_1, node.m_Text_1); if (node.has_Text_2()) SET_FIELD(Text_2, node.m_Text_2); if (node.has_Blob_1()) SET_FIELD(Blob_1, DS::Base64Encode(node.m_Blob_1.buffer(), node.m_Blob_1.size())); if (node.has_Blob_2()) SET_FIELD(Blob_2, DS::Base64Encode(node.m_Blob_2.buffer(), node.m_Blob_2.size())); #undef SET_FIELD DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 1) = ')'; // Get rid of the last comma DS::String queryStr = "INSERT INTO vault.\"Nodes\" ("; queryStr += fieldbuf; fieldp = fieldbuf; for (size_t i=0; i<parmcount; ++i) { sprintf(fieldp, "$%Zu,", i+1); fieldp += strlen(fieldp); } DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 1) = ')'; // Get rid of the last comma queryStr += "\n VALUES ("; queryStr += fieldbuf; queryStr += "\n RETURNING idx"; check_postgres(); PGresult* result = PQexecParams(s_postgres, queryStr.c_str(), parmcount, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres INSERT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return 0; } DS_DASSERT(PQntuples(result) == 1); uint32_t idx = strtoul(PQgetvalue(result, 0, 0), 0, 10); PQclear(result); return idx; }
std::tuple<uint32_t, uint32_t> v_create_age(AuthServer_AgeInfo age, uint32_t flags) { if (age.m_ageId.isNull()) age.m_ageId = gen_uuid(); int seqNumber = age.m_seqNumber; if (seqNumber < 0) { check_postgres(); PGresult* result = PQexec(s_postgres, "SELECT nextval('game.\"AgeSeqNumber\"'::regclass)"); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres SELECT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return std::make_pair(0, 0); } DS_DASSERT(PQntuples(result) == 1); seqNumber = strtol(PQgetvalue(result, 0, 0), 0, 10); PQclear(result); } DS::Vault::Node node; node.set_NodeType(DS::Vault::e_NodeAge); node.set_CreatorUuid(age.m_ageId); node.set_Uuid_1(age.m_ageId); if (!age.m_parentId.isNull()) node.set_Uuid_2(age.m_parentId); node.set_String64_1(age.m_filename); uint32_t ageNode = v_create_node(node); if (ageNode == 0) return std::make_pair(0, 0); // TODO: Global SDL node node.clear(); node.set_NodeType(DS::Vault::e_NodeFolder); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_ChronicleFolder); uint32_t chronFolder = v_create_node(node); if (chronFolder == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodePlayerInfoList); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_PeopleIKnowAboutFolder); uint32_t knownFolder = v_create_node(node); if (knownFolder == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodeAgeInfoList); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_SubAgesFolder); uint32_t subAgesFolder = v_create_node(node); if (subAgesFolder == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodeAgeInfo); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(seqNumber); node.set_Int32_2((flags & e_AgePublic) != 0 ? 1 : 0); node.set_Int32_3(age.m_language); node.set_Uint32_1(ageNode); node.set_Uint32_2(0); // Czar ID node.set_Uint32_3(0); // Flags node.set_Uuid_1(age.m_ageId); if (!age.m_parentId.isNull()) node.set_Uuid_2(age.m_parentId); node.set_String64_2(age.m_filename); if (!age.m_instName.isNull()) node.set_String64_3(age.m_instName); if (!age.m_userName.isEmpty()) node.set_String64_4(age.m_userName); if (!age.m_description.isEmpty()) node.set_Text_1(age.m_description); uint32_t ageInfoNode = v_create_node(node); if (ageInfoNode == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodeFolder); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_AgeDevicesFolder); uint32_t devsFolder = v_create_node(node); if (devsFolder == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodePlayerInfoList); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_CanVisitFolder); uint32_t canVisitList = v_create_node(node); if (canVisitList == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodeSDL); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(0); node.set_String64_1(age.m_filename); node.set_Blob_1(gen_default_sdl(age.m_filename)); uint32_t ageSdlNode = v_create_node(node); if (ageSdlNode == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodePlayerInfoList); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_AgeOwnersFolder); uint32_t ageOwners = v_create_node(node); if (ageOwners == 0) return std::make_pair(0, 0); node.clear(); node.set_NodeType(DS::Vault::e_NodeAgeInfoList); node.set_CreatorUuid(age.m_ageId); node.set_CreatorIdx(ageNode); node.set_Int32_1(DS::Vault::e_ChildAgesFolder); uint32_t childAges = v_create_node(node); if (childAges == 0) return std::make_pair(0, 0); if (!v_ref_node(ageNode, s_systemNode, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageNode, chronFolder, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageNode, knownFolder, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageNode, subAgesFolder, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageNode, ageInfoNode, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageNode, devsFolder, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageInfoNode, canVisitList, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageInfoNode, ageSdlNode, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageInfoNode, ageOwners, 0)) return std::make_pair(0, 0); if (!v_ref_node(ageInfoNode, childAges, 0)) return std::make_pair(0, 0); // Register with the server database { DS::String agedesc = !age.m_description.isEmpty() ? age.m_description : !age.m_instName.isEmpty() ? age.m_instName : age.m_filename; PostgresStrings<5> parms; parms.set(0, age.m_ageId.toString()); parms.set(1, age.m_filename); parms.set(2, agedesc); parms.set(3, ageNode); parms.set(4, ageSdlNode); PGresult* result = PQexecParams(s_postgres, "INSERT INTO game.\"Servers\"" " (\"AgeUuid\", \"AgeFilename\", \"DisplayName\", \"AgeIdx\", \"SdlIdx\")" " VALUES ($1, $2, $3, $4, $5)", 5, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, "%s:%d:\n Postgres INSERT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return std::make_pair(0, 0); } PQclear(result); } return std::make_tuple(ageNode, ageInfoNode); }
bool v_find_nodes(const DS::Vault::Node& nodeTemplate, std::vector<uint32_t>& nodes) { if (nodeTemplate.isNull()) return false; /* This should be plenty to store everything we need without a bunch * of dynamic reallocations */ PostgresStrings<31> parms; char fieldbuf[1024]; size_t parmcount = 0; char* fieldp = fieldbuf; #define SET_FIELD(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "\"" #name "\"=$%Zu AND ", parmcount); \ } #define SET_FIELD_I(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "LOWER(\"" #name "\")=LOWER($%Zu) AND ", parmcount); \ } if (nodeTemplate.has_CreateTime()) SET_FIELD(CreateTime, nodeTemplate.m_CreateTime); if (nodeTemplate.has_ModifyTime()) SET_FIELD(ModifyTime, nodeTemplate.m_ModifyTime); if (nodeTemplate.has_CreateAgeName()) SET_FIELD(CreateAgeName, nodeTemplate.m_CreateAgeName); if (nodeTemplate.has_CreateAgeUuid()) SET_FIELD(CreateAgeUuid, nodeTemplate.m_CreateAgeUuid.toString()); if (nodeTemplate.has_CreatorUuid()) SET_FIELD(CreatorUuid, nodeTemplate.m_CreatorUuid.toString()); if (nodeTemplate.has_CreatorIdx()) SET_FIELD(CreatorIdx, nodeTemplate.m_CreatorIdx); if (nodeTemplate.has_NodeType()) SET_FIELD(NodeType, nodeTemplate.m_NodeType); if (nodeTemplate.has_Int32_1()) SET_FIELD(Int32_1, nodeTemplate.m_Int32_1); if (nodeTemplate.has_Int32_2()) SET_FIELD(Int32_2, nodeTemplate.m_Int32_2); if (nodeTemplate.has_Int32_3()) SET_FIELD(Int32_3, nodeTemplate.m_Int32_3); if (nodeTemplate.has_Int32_4()) SET_FIELD(Int32_4, nodeTemplate.m_Int32_4); if (nodeTemplate.has_Uint32_1()) SET_FIELD(Uint32_1, nodeTemplate.m_Uint32_1); if (nodeTemplate.has_Uint32_2()) SET_FIELD(Uint32_2, nodeTemplate.m_Uint32_2); if (nodeTemplate.has_Uint32_3()) SET_FIELD(Uint32_3, nodeTemplate.m_Uint32_3); if (nodeTemplate.has_Uint32_4()) SET_FIELD(Uint32_4, nodeTemplate.m_Uint32_4); if (nodeTemplate.has_Uuid_1()) SET_FIELD(Uuid_1, nodeTemplate.m_Uuid_1.toString()); if (nodeTemplate.has_Uuid_2()) SET_FIELD(Uuid_2, nodeTemplate.m_Uuid_2.toString()); if (nodeTemplate.has_Uuid_3()) SET_FIELD(Uuid_3, nodeTemplate.m_Uuid_3.toString()); if (nodeTemplate.has_Uuid_4()) SET_FIELD(Uuid_4, nodeTemplate.m_Uuid_4.toString()); if (nodeTemplate.has_String64_1()) SET_FIELD(String64_1, nodeTemplate.m_String64_1); if (nodeTemplate.has_String64_2()) SET_FIELD(String64_2, nodeTemplate.m_String64_2); if (nodeTemplate.has_String64_3()) SET_FIELD(String64_3, nodeTemplate.m_String64_3); if (nodeTemplate.has_String64_4()) SET_FIELD(String64_4, nodeTemplate.m_String64_4); if (nodeTemplate.has_String64_5()) SET_FIELD(String64_5, nodeTemplate.m_String64_5); if (nodeTemplate.has_String64_6()) SET_FIELD(String64_6, nodeTemplate.m_String64_6); if (nodeTemplate.has_IString64_1()) SET_FIELD_I(IString64_1, nodeTemplate.m_IString64_1); if (nodeTemplate.has_IString64_2()) SET_FIELD_I(IString64_2, nodeTemplate.m_IString64_2); if (nodeTemplate.has_Text_1()) SET_FIELD(Text_1, nodeTemplate.m_Text_1); if (nodeTemplate.has_Text_2()) SET_FIELD(Text_2, nodeTemplate.m_Text_2); if (nodeTemplate.has_Blob_1()) SET_FIELD(Blob_1, DS::Base64Encode(nodeTemplate.m_Blob_1.buffer(), nodeTemplate.m_Blob_1.size())); if (nodeTemplate.has_Blob_2()) SET_FIELD(Blob_2, DS::Base64Encode(nodeTemplate.m_Blob_2.buffer(), nodeTemplate.m_Blob_2.size())); #undef SET_FIELD #undef SET_FIELD_I DS_DASSERT(parmcount > 0); DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 5) = 0; // Get rid of the last ' AND ' DS::String queryStr = "SELECT idx FROM vault.\"Nodes\"\n WHERE "; queryStr += fieldbuf; check_postgres(); PGresult* result = PQexecParams(s_postgres, queryStr.c_str(), parmcount, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres SELECT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return false; } nodes.resize(PQntuples(result)); for (size_t i=0; i<nodes.size(); ++i) nodes[i] = strtoul(PQgetvalue(result, i, 0), 0, 10); PQclear(result); return true; }