You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PgSql.cpp 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //
  2. // Created by robin on 4/6/16.
  3. //
  4. #include <fstream>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include "PgSql.h"
  8. #define tmpTemplate "/tmp/pdns-slave.XXXXXX"
  9. PgSql::PgSql(const SqlConfiguration &masterConfig, const SqlConfiguration &slaveConfig)
  10. : AbstractSql(masterConfig, slaveConfig)
  11. {
  12. }
  13. PgSql::~PgSql()
  14. {
  15. if (!_dumpFilePath.empty())
  16. {
  17. unlink(_dumpFilePath.c_str());
  18. _dumpFilePath = "";
  19. }
  20. if (!_overrideFilePath.empty())
  21. {
  22. unlink(_overrideFilePath.c_str());
  23. _overrideFilePath = "";
  24. }
  25. }
  26. BResult PgSql::dump()
  27. {
  28. BResult res;
  29. _dumpFilePath = getTempFile();
  30. auto command = std::string("PGPASSWORD='" + _masterConfig.getPassword() + "' "
  31. + "pg_dump -h '" + _masterConfig.getHost() + "' "
  32. + "-U '" + _masterConfig.getUser() + "' "
  33. + "-w -c -x -O '" + _masterConfig.getDatabase() + "' "
  34. + "> '" + _dumpFilePath + "'");
  35. int status = system(command.c_str());
  36. if (status == 0)
  37. return res.ok(true);
  38. return res.error("pg_dump exited with code " + std::to_string(status));
  39. }
  40. const std::string PgSql::getTempFile()
  41. {
  42. char tmp[sizeof(tmpTemplate)];
  43. strcpy(tmp, tmpTemplate);
  44. mkstemp(tmp);
  45. return std::string(tmp);
  46. }
  47. BResult PgSql::insert()
  48. {
  49. return insertSlave(_dumpFilePath);
  50. }
  51. BResult PgSql::override(const std::string &sql)
  52. {
  53. _overrideFilePath = getTempFile();
  54. std::ofstream file(_overrideFilePath);
  55. if (!file)
  56. return BResult().error("Could not open temp file " + _overrideFilePath);
  57. file << sql;
  58. file.close();
  59. return insertSlave(_overrideFilePath);
  60. }
  61. BResult PgSql::insertSlave(const std::string &file)
  62. {
  63. BResult res;
  64. auto command = std::string("cat '" + file + "' | PGPASSWORD='" + _slaveConfig.getPassword() + "' "
  65. + "psql -h '" + _slaveConfig.getHost() + "' "
  66. + "-U '" + _slaveConfig.getUser() + "' "
  67. + "-w -d '" + _slaveConfig.getDatabase() + "' > /dev/null");
  68. int status = system(command.c_str());
  69. if (status == 0)
  70. return res.ok(true);
  71. return res.error("psql exited with code " + std::to_string(status));
  72. }
  73. std::string PgSql::getAddDomainQuery(const ActionAddDomain &action)
  74. {
  75. auto soa = action.getSoaNs() + " " + action.getSoaMail() + " " + std::to_string(time(nullptr)) + " "
  76. + std::to_string(action.getSoaRefresh()) + " " + std::to_string(action.getSoaRetry()) + " "
  77. + std::to_string(action.getSoaExpire()) + " " + std::to_string(action.getSoaTtl());
  78. return "INSERT INTO domains (name, type) VALUES (\'" + action.getDomain() + "\', \'MASTER\');\n"
  79. "INSERT INTO zones (domain_id, owner, zone_templ_id) VALUES "
  80. "((SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\'), "
  81. "(SELECT id FROM users ORDER BY id LIMIT 1), 0);\n"
  82. "INSERT INTO records (domain_id, name, type, content, ttl, prio, change_date)\n"
  83. " VALUES((SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\'), \'"
  84. + action.getDomain() + "\', \'SOA\', \'" + soa + "\', " + std::to_string(action.getTtl()) + ", 0, "
  85. + std::to_string(time(nullptr)) + ");\n";
  86. }
  87. std::string PgSql::getAddHostQuery(const ActionAddHost &action)
  88. {
  89. auto host = action.getHost().empty() ? action.getDomain() : action.getHost() + "." + action.getDomain();
  90. auto query = "INSERT INTO records (domain_id, name, type, content, ttl, prio, change_date)\n"
  91. " VALUES((SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\'), \'"
  92. + host + "\', \'" + action.getRecordType() + "\', \'"
  93. + action.getRecordValue() + "\', " + std::to_string(action.getTtl())
  94. + ", 0, " + std::to_string(time(nullptr)) + ");\n";
  95. if (action.isReverseEnabled() && action.getRecordType() == "A")
  96. {
  97. auto reversedValue = action.getReversedValue();
  98. auto reverseDomain = action.getReverseDomain().empty() ? "in-addr.arpa" :
  99. action.getReverseDomain() + ".in-addr.arpa";
  100. query += "INSERT INTO records (domain_id, name, type, content, ttl, prio, change_date)\n"
  101. " VALUES((SELECT id FROM domains WHERE name=\'" + reverseDomain + "\'), \'"
  102. + reversedValue + "." + reverseDomain + "\', \'PTR\', \'" + action.getHost()
  103. + "." + action.getDomain() + "\', " + std::to_string(action.getTtl()) + ", 0, "
  104. + std::to_string(time(nullptr)) + ");\n";
  105. }
  106. return query;
  107. }
  108. std::string PgSql::getDelDomainQuery(const ActionDelDomain &action)
  109. {
  110. return "DELETE FROM records WHERE domain_id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');\n"
  111. "DELETE FROM comments WHERE domain_id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');\n"
  112. "DELETE FROM zones WHERE domain_id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');\n"
  113. "DELETE FROM cryptokeys WHERE domain_id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');\n"
  114. "DELETE FROM domainmetadata WHERE domain_id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');\n"
  115. "DELETE FROM domains WHERE id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');\n";
  116. }
  117. std::string PgSql::getDelHostQuery(const ActionDelHost &action)
  118. {
  119. return "DELETE FROM records WHERE name=\'" + action.getHost() + "." + action.getDomain() + "\' AND "
  120. "domain_id=(SELECT id FROM domains WHERE name=\'" + action.getDomain() + "\');";
  121. }