]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/backends/gsql/gsqlbackend.cc
make DomainInfo not carry IP addresses as strings. And some subsequent cleanups..
[thirdparty/pdns.git] / pdns / backends / gsql / gsqlbackend.cc
CommitLineData
0ea9281e 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
b4ce8b4e
BH
25#include "pdns/dns.hh"
26#include "pdns/dnsbackend.hh"
27#include "gsqlbackend.hh"
28#include "pdns/dnspacket.hh"
5c409fa2 29#include "pdns/pdnsexception.hh"
b4ce8b4e
BH
30#include "pdns/logger.hh"
31#include "pdns/arguments.hh"
f9cf6d92
KM
32#include "pdns/base32.hh"
33#include "pdns/dnssecinfra.hh"
f7df9b0f 34#include <boost/algorithm/string.hpp>
b4ce8b4e 35#include <sstream>
f7bcc763 36#include <boost/format.hpp>
0f310932 37#include <boost/scoped_ptr.hpp>
78bcb858 38
63be3701 39#define ASSERT_ROW_COLUMNS(query, row, num) { if (row.size() != num) { throw PDNSException(std::string(query) + " returned wrong number of columns, expected " #num ", got " + std::to_string(row.size())); } }
7c779a31 40
0f310932
AT
41GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
42{
43 setArgPrefix(mode+suffix);
44 d_db=0;
45 d_logprefix="["+mode+"Backend"+suffix+"] ";
46
47 try
48 {
49 d_dnssecQueries = mustDo("dnssec");
50 }
51 catch (ArgException e)
52 {
53 d_dnssecQueries = false;
54 }
55
56 d_NoIdQuery=getArg("basic-query");
57 d_IdQuery=getArg("id-query");
58 d_ANYNoIdQuery=getArg("any-query");
59 d_ANYIdQuery=getArg("any-id-query");
60
61 d_listQuery=getArg("list-query");
62 d_listSubZoneQuery=getArg("list-subzone-query");
63
0f310932
AT
64 d_InfoOfDomainsZoneQuery=getArg("info-zone-query");
65 d_InfoOfAllSlaveDomainsQuery=getArg("info-all-slaves-query");
66 d_SuperMasterInfoQuery=getArg("supermaster-query");
67 d_GetSuperMasterIPs=getArg("supermaster-name-to-ips");
68 d_InsertZoneQuery=getArg("insert-zone-query");
0f310932 69 d_InsertRecordQuery=getArg("insert-record-query");
0f310932
AT
70 d_UpdateMasterOfZoneQuery=getArg("update-master-query");
71 d_UpdateKindOfZoneQuery=getArg("update-kind-query");
72 d_UpdateSerialOfZoneQuery=getArg("update-serial-query");
73 d_UpdateLastCheckofZoneQuery=getArg("update-lastcheck-query");
79532aa7 74 d_UpdateAccountOfZoneQuery=getArg("update-account-query");
0f310932
AT
75 d_ZoneLastChangeQuery=getArg("zone-lastchange-query");
76 d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query");
77 d_DeleteDomainQuery=getArg("delete-domain-query");
78 d_DeleteZoneQuery=getArg("delete-zone-query");
79 d_DeleteRRSetQuery=getArg("delete-rrset-query");
80 d_DeleteNamesQuery=getArg("delete-names-query");
81 d_getAllDomainsQuery=getArg("get-all-domains-query");
82
09070ce7
PL
83 d_InsertEmptyNonTerminalOrderQuery=getArg("insert-empty-non-terminal-order-query");
84 d_DeleteEmptyNonTerminalQuery = getArg("delete-empty-non-terminal-query");
85 d_RemoveEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query");
de43ec0f 86
0f310932
AT
87 d_ListCommentsQuery = getArg("list-comments-query");
88 d_InsertCommentQuery = getArg("insert-comment-query");
89 d_DeleteCommentRRsetQuery = getArg("delete-comment-rrset-query");
90 d_DeleteCommentsQuery = getArg("delete-comments-query");
91
0f310932
AT
92 d_firstOrderQuery = getArg("get-order-first-query");
93 d_beforeOrderQuery = getArg("get-order-before-query");
94 d_afterOrderQuery = getArg("get-order-after-query");
95 d_lastOrderQuery = getArg("get-order-last-query");
79de0a80
KM
96
97 d_updateOrderNameAndAuthQuery = getArg("update-ordername-and-auth-query");
98 d_updateOrderNameAndAuthTypeQuery = getArg("update-ordername-and-auth-type-query");
0f310932 99 d_nullifyOrderNameAndUpdateAuthQuery = getArg("nullify-ordername-and-update-auth-query");
79de0a80 100 d_nullifyOrderNameAndUpdateAuthTypeQuery = getArg("nullify-ordername-and-update-auth-type-query");
0f310932
AT
101
102 d_AddDomainKeyQuery = getArg("add-domain-key-query");
63de5311 103 d_GetLastInsertedKeyIdQuery = getArg("get-last-inserted-key-id-query");
0f310932
AT
104 d_ListDomainKeysQuery = getArg("list-domain-keys-query");
105
106 d_GetAllDomainMetadataQuery = getArg("get-all-domain-metadata-query");
107 d_GetDomainMetadataQuery = getArg("get-domain-metadata-query");
108 d_ClearDomainMetadataQuery = getArg("clear-domain-metadata-query");
109 d_ClearDomainAllMetadataQuery = getArg("clear-domain-all-metadata-query");
110 d_SetDomainMetadataQuery = getArg("set-domain-metadata-query");
111
112 d_ActivateDomainKeyQuery = getArg("activate-domain-key-query");
113 d_DeactivateDomainKeyQuery = getArg("deactivate-domain-key-query");
114 d_RemoveDomainKeyQuery = getArg("remove-domain-key-query");
115 d_ClearDomainAllKeysQuery = getArg("clear-domain-all-keys-query");
116
117 d_getTSIGKeyQuery = getArg("get-tsig-key-query");
118 d_setTSIGKeyQuery = getArg("set-tsig-key-query");
119 d_deleteTSIGKeyQuery = getArg("delete-tsig-key-query");
120 d_getTSIGKeysQuery = getArg("get-tsig-keys-query");
121
474cacfa
AT
122 d_SearchRecordsQuery = getArg("search-records-query");
123 d_SearchCommentsQuery = getArg("search-comments-query");
124
1750b440 125 d_query_stmt = NULL;
0f310932
AT
126 d_NoIdQuery_stmt = NULL;
127 d_IdQuery_stmt = NULL;
128 d_ANYNoIdQuery_stmt = NULL;
129 d_ANYIdQuery_stmt = NULL;
130 d_listQuery_stmt = NULL;
131 d_listSubZoneQuery_stmt = NULL;
0f310932
AT
132 d_InfoOfDomainsZoneQuery_stmt = NULL;
133 d_InfoOfAllSlaveDomainsQuery_stmt = NULL;
134 d_SuperMasterInfoQuery_stmt = NULL;
135 d_GetSuperMasterIPs_stmt = NULL;
136 d_InsertZoneQuery_stmt = NULL;
0f310932 137 d_InsertRecordQuery_stmt = NULL;
09070ce7 138 d_InsertEmptyNonTerminalOrderQuery_stmt = NULL;
0f310932
AT
139 d_UpdateMasterOfZoneQuery_stmt = NULL;
140 d_UpdateKindOfZoneQuery_stmt = NULL;
141 d_UpdateSerialOfZoneQuery_stmt = NULL;
142 d_UpdateLastCheckofZoneQuery_stmt = NULL;
79532aa7 143 d_UpdateAccountOfZoneQuery_stmt = NULL;
0f310932
AT
144 d_InfoOfAllMasterDomainsQuery_stmt = NULL;
145 d_DeleteDomainQuery_stmt = NULL;
146 d_DeleteZoneQuery_stmt = NULL;
147 d_DeleteRRSetQuery_stmt = NULL;
148 d_DeleteNamesQuery_stmt = NULL;
149 d_ZoneLastChangeQuery_stmt = NULL;
150 d_firstOrderQuery_stmt = NULL;
151 d_beforeOrderQuery_stmt = NULL;
152 d_afterOrderQuery_stmt = NULL;
153 d_lastOrderQuery_stmt = NULL;
79de0a80
KM
154 d_updateOrderNameAndAuthQuery_stmt = NULL;
155 d_updateOrderNameAndAuthTypeQuery_stmt = NULL;
0f310932 156 d_nullifyOrderNameAndUpdateAuthQuery_stmt = NULL;
79de0a80 157 d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt = NULL;
09070ce7
PL
158 d_RemoveEmptyNonTerminalsFromZoneQuery_stmt = NULL;
159 d_DeleteEmptyNonTerminalQuery_stmt = NULL;
0f310932 160 d_AddDomainKeyQuery_stmt = NULL;
63de5311 161 d_GetLastInsertedKeyIdQuery_stmt = NULL;
0f310932
AT
162 d_ListDomainKeysQuery_stmt = NULL;
163 d_GetAllDomainMetadataQuery_stmt = NULL;
164 d_GetDomainMetadataQuery_stmt = NULL;
165 d_ClearDomainMetadataQuery_stmt = NULL;
166 d_ClearDomainAllMetadataQuery_stmt = NULL;
167 d_SetDomainMetadataQuery_stmt = NULL;
168 d_RemoveDomainKeyQuery_stmt = NULL;
169 d_ActivateDomainKeyQuery_stmt = NULL;
170 d_DeactivateDomainKeyQuery_stmt = NULL;
171 d_ClearDomainAllKeysQuery_stmt = NULL;
172 d_getTSIGKeyQuery_stmt = NULL;
173 d_setTSIGKeyQuery_stmt = NULL;
174 d_deleteTSIGKeyQuery_stmt = NULL;
175 d_getTSIGKeysQuery_stmt = NULL;
176 d_getAllDomainsQuery_stmt = NULL;
177 d_ListCommentsQuery_stmt = NULL;
178 d_InsertCommentQuery_stmt = NULL;
179 d_DeleteCommentRRsetQuery_stmt = NULL;
180 d_DeleteCommentsQuery_stmt = NULL;
474cacfa
AT
181 d_SearchRecordsQuery_stmt = NULL;
182 d_SearchCommentsQuery_stmt = NULL;
d2dbd785 183}
b4ce8b4e 184
092f210a 185void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial)
b4ce8b4e
BH
186{
187 try {
45d36933
RG
188 reconnectIfNeeded();
189
0f310932
AT
190 d_UpdateSerialOfZoneQuery_stmt->
191 bind("serial", serial)->
192 bind("domain_id", domain_id)->
193 execute()->
194 reset();
b4ce8b4e
BH
195 }
196 catch(SSqlException &e) {
63be3701 197 throw PDNSException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason());
b4ce8b4e
BH
198 }
199}
200
092f210a 201void GSQLBackend::setFresh(uint32_t domain_id)
b4ce8b4e
BH
202{
203 try {
45d36933
RG
204 reconnectIfNeeded();
205
0f310932
AT
206 d_UpdateLastCheckofZoneQuery_stmt->
207 bind("last_check", time(0))->
208 bind("domain_id", domain_id)->
209 execute()->
210 reset();
b4ce8b4e
BH
211 }
212 catch (SSqlException &e) {
63be3701 213 throw PDNSException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason());
b4ce8b4e
BH
214 }
215}
216
223d3559 217bool GSQLBackend::setMaster(const DNSName &domain, const string &ip)
c02f13ef 218{
c02f13ef 219 try {
45d36933
RG
220 reconnectIfNeeded();
221
0f310932
AT
222 d_UpdateMasterOfZoneQuery_stmt->
223 bind("master", ip)->
223d3559 224 bind("domain", domain)->
0f310932
AT
225 execute()->
226 reset();
c02f13ef
CH
227 }
228 catch (SSqlException &e) {
2042adf5 229 throw PDNSException("GSQLBackend unable to set master of domain '"+domain.toLogString()+"': "+e.txtReason());
c02f13ef
CH
230 }
231 return true;
232}
233
223d3559 234bool GSQLBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind kind)
c02f13ef 235{
c02f13ef 236 try {
45d36933
RG
237 reconnectIfNeeded();
238
0f310932
AT
239 d_UpdateKindOfZoneQuery_stmt->
240 bind("kind", toUpper(DomainInfo::getKindString(kind)))->
223d3559 241 bind("domain", domain)->
0f310932
AT
242 execute()->
243 reset();
c02f13ef
CH
244 }
245 catch (SSqlException &e) {
2042adf5 246 throw PDNSException("GSQLBackend unable to set kind of domain '"+domain.toLogString()+"': "+e.txtReason());
c02f13ef
CH
247 }
248 return true;
249}
250
223d3559 251bool GSQLBackend::setAccount(const DNSName &domain, const string &account)
79532aa7
CH
252{
253 try {
45d36933
RG
254 reconnectIfNeeded();
255
79532aa7
CH
256 d_UpdateAccountOfZoneQuery_stmt->
257 bind("account", account)->
223d3559 258 bind("domain", domain)->
79532aa7
CH
259 execute()->
260 reset();
261 }
262 catch (SSqlException &e) {
2042adf5 263 throw PDNSException("GSQLBackend unable to set account of domain '"+domain.toLogString()+"': "+e.txtReason());
79532aa7
CH
264 }
265 return true;
266}
267
47bddbb7 268bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial)
b4ce8b4e 269{
85b8554f 270 /* fill DomainInfo from database info:
8ffb7a9b 271 id,name,master IP(s),last_check,notified_serial,type,account */
b4ce8b4e 272 try {
45d36933
RG
273 reconnectIfNeeded();
274
0f310932 275 d_InfoOfDomainsZoneQuery_stmt->
8f126bc1 276 bind("domain", domain)->
0f310932
AT
277 execute()->
278 getResult(d_result)->
279 reset();
b4ce8b4e
BH
280 }
281 catch(SSqlException &e) {
63be3701 282 throw PDNSException("GSQLBackend unable to retrieve information about a domain: "+e.txtReason());
b4ce8b4e
BH
283 }
284
285 int numanswers=d_result.size();
286 if(!numanswers)
287 return false;
7c779a31
AT
288
289 ASSERT_ROW_COLUMNS("info-zone-query", d_result[0], 7);
290
955e760a 291 di.id=pdns_stou(d_result[0][0]);
8408d2a6
KM
292 try {
293 di.zone=DNSName(d_result[0][1]);
294 } catch (...) {
295 return false;
296 }
d622042f 297 vector<string> masters;
298 stringtok(masters, d_result[0][2], " ,\t");
299 for(const auto& m : masters)
300 di.masters.emplace_back(m, 53);
955e760a
AT
301 di.last_check=pdns_stou(d_result[0][3]);
302 di.notified_serial = pdns_stou(d_result[0][4]);
326a1978 303 string type=d_result[0][5];
8ffb7a9b 304 di.account=d_result[0][6];
b4ce8b4e 305 di.backend=this;
85b8554f
CH
306
307 di.serial = 0;
47bddbb7
KM
308 if(getSerial) {
309 try {
310 SOAData sd;
311 if(!getSOA(domain, sd))
312 g_log<<Logger::Notice<<"No serial for '"<<domain<<"' found - zone is missing?"<<endl;
313 else
314 di.serial = sd.serial;
315 }
316 catch(PDNSException &ae){
317 g_log<<Logger::Error<<"Error retrieving serial for '"<<domain<<"': "<<ae.reason<<endl;
318 }
85b8554f
CH
319 }
320
76979e74 321 di.kind = DomainInfo::stringToKind(type);
85b8554f 322
b4ce8b4e
BH
323 return true;
324}
325
326void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
327{
328 /* list all domains that need refreshing for which we are slave, and insert into SlaveDomain:
329 id,name,master IP,serial */
b4ce8b4e 330 try {
45d36933
RG
331 reconnectIfNeeded();
332
0f310932
AT
333 d_InfoOfAllSlaveDomainsQuery_stmt->
334 execute()->
335 getResult(d_result)->
336 reset();
b4ce8b4e
BH
337 }
338 catch (SSqlException &e) {
63be3701 339 throw PDNSException("GSQLBackend unable to retrieve list of slave domains: "+e.txtReason());
b4ce8b4e
BH
340 }
341
e1602f7a 342 vector<DomainInfo> allSlaves;
b4ce8b4e
BH
343 int numanswers=d_result.size();
344 for(int n=0;n<numanswers;++n) { // id,name,master,last_check
345 DomainInfo sd;
7c779a31 346 ASSERT_ROW_COLUMNS("info-all-slaves-query", d_result[n], 4);
955e760a 347 sd.id=pdns_stou(d_result[n][0]);
8408d2a6
KM
348 try {
349 sd.zone= DNSName(d_result[n][1]);
350 } catch (...) {
351 continue;
352 }
d622042f 353
354 vector<string> masters;
355 stringtok(masters, d_result[n][2], ", \t");
356 for(const auto& m : masters)
357 sd.masters.emplace_back(m, 53);
358
955e760a 359 sd.last_check=pdns_stou(d_result[n][3]);
b4ce8b4e
BH
360 sd.backend=this;
361 sd.kind=DomainInfo::Slave;
362 allSlaves.push_back(sd);
363 }
364
365 for(vector<DomainInfo>::iterator i=allSlaves.begin();i!=allSlaves.end();++i) {
366 SOAData sdata;
367 sdata.serial=0;
368 sdata.refresh=0;
369 getSOA(i->zone,sdata);
370 if((time_t)(i->last_check+sdata.refresh) < time(0)) {
371 i->serial=sdata.serial;
372 unfreshDomains->push_back(*i);
373 }
374 }
375}
376
377void GSQLBackend::getUpdatedMasters(vector<DomainInfo> *updatedDomains)
378{
379 /* list all domains that need notifications for which we are master, and insert into updatedDomains
380 id,name,master IP,serial */
b4ce8b4e 381 try {
45d36933
RG
382 reconnectIfNeeded();
383
0f310932
AT
384 d_InfoOfAllMasterDomainsQuery_stmt->
385 execute()->
386 getResult(d_result)->
387 reset();
b4ce8b4e
BH
388 }
389 catch(SSqlException &e) {
63be3701 390 throw PDNSException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason());
b4ce8b4e
BH
391 }
392
e5b11b2f 393 vector<DomainInfo> allMasters;
abcd36a1
CH
394 size_t numanswers=d_result.size();
395 for(size_t n=0;n<numanswers;++n) { // id,name,master,last_check,notified_serial
b4ce8b4e 396 DomainInfo sd;
30c9a6d9 397 ASSERT_ROW_COLUMNS("info-all-master-query", d_result[n], 6);
955e760a 398 sd.id=pdns_stou(d_result[n][0]);
8408d2a6
KM
399 try {
400 sd.zone= DNSName(d_result[n][1]);
401 } catch (...) {
402 continue;
403 }
955e760a
AT
404 sd.last_check=pdns_stou(d_result[n][3]);
405 sd.notified_serial=pdns_stou(d_result[n][4]);
b4ce8b4e
BH
406 sd.backend=this;
407 sd.kind=DomainInfo::Master;
408 allMasters.push_back(sd);
409 }
410
411 for(vector<DomainInfo>::iterator i=allMasters.begin();i!=allMasters.end();++i) {
412 SOAData sdata;
413 sdata.serial=0;
414 sdata.refresh=0;
415 getSOA(i->zone,sdata);
416 if(i->notified_serial!=sdata.serial) {
417 i->serial=sdata.serial;
418 updatedDomains->push_back(*i);
419 }
420 }
421}
422
96e63d77 423bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype)
27045410
PD
424{
425 if(!d_dnssecQueries)
426 return false;
c2df797e 427
79de0a80
KM
428 if (!ordername.empty()) {
429 if (qtype == QType::ANY) {
430 try {
45d36933
RG
431 reconnectIfNeeded();
432
79de0a80 433 d_updateOrderNameAndAuthQuery_stmt->
96e63d77 434 bind("ordername", ordername.labelReverse().toString(" ", false))->
79de0a80
KM
435 bind("auth", auth)->
436 bind("domain_id", domain_id)->
437 bind("qname", qname)->
438 execute()->
439 reset();
440 }
441 catch(SSqlException &e) {
63be3701 442 throw PDNSException("GSQLBackend unable to update ordername and auth for domain_id "+itoa(domain_id)+": "+e.txtReason());
79de0a80
KM
443 }
444 } else {
445 try {
45d36933
RG
446 reconnectIfNeeded();
447
79de0a80 448 d_updateOrderNameAndAuthTypeQuery_stmt->
96e63d77 449 bind("ordername", ordername.labelReverse().toString(" ", false))->
79de0a80
KM
450 bind("auth", auth)->
451 bind("domain_id", domain_id)->
452 bind("qname", qname)->
453 bind("qtype", QType(qtype).getName())->
454 execute()->
455 reset();
456 }
457 catch(SSqlException &e) {
63be3701 458 throw PDNSException("GSQLBackend unable to update ordername and auth per type for domain_id "+itoa(domain_id)+": "+e.txtReason());
79de0a80
KM
459 }
460 }
461 } else {
462 if (qtype == QType::ANY) {
45d36933
RG
463 reconnectIfNeeded();
464
79de0a80
KM
465 try {
466 d_nullifyOrderNameAndUpdateAuthQuery_stmt->
467 bind("auth", auth)->
468 bind("domain_id", domain_id)->
469 bind("qname", qname)->
470 execute()->
471 reset();
472 }
473 catch(SSqlException &e) {
63be3701 474 throw PDNSException("GSQLBackend unable to nullify ordername and update auth for domain_id "+itoa(domain_id)+": "+e.txtReason());
79de0a80
KM
475 }
476 } else {
477 try {
45d36933
RG
478 reconnectIfNeeded();
479
79de0a80
KM
480 d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt->
481 bind("auth", auth)->
482 bind("domain_id", domain_id)->
483 bind("qname", qname)->
484 bind("qtype", QType(qtype).getName())->
485 execute()->
486 reset();
487 }
488 catch(SSqlException &e) {
63be3701 489 throw PDNSException("GSQLBackend unable to nullify ordername and update auth per type for domain_id "+itoa(domain_id)+": "+e.txtReason());
79de0a80
KM
490 }
491 }
bb6dd39e 492 }
27045410
PD
493 return true;
494}
495
96e63d77 496bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove)
b5baefaf 497{
b5baefaf 498 if(remove) {
b5baefaf 499 try {
45d36933
RG
500 reconnectIfNeeded();
501
09070ce7 502 d_RemoveEmptyNonTerminalsFromZoneQuery_stmt->
0f310932
AT
503 bind("domain_id", domain_id)->
504 execute()->
505 reset();
b5baefaf
PD
506 }
507 catch (SSqlException &e) {
63be3701 508 throw PDNSException("GSQLBackend unable to delete empty non-terminal records from domain_id "+itoa(domain_id)+": "+e.txtReason());
b5baefaf
PD
509 return false;
510 }
511 }
512 else
513 {
424b92c6 514 for(const auto& qname: erase) {
b5baefaf 515 try {
45d36933
RG
516 reconnectIfNeeded();
517
09070ce7 518 d_DeleteEmptyNonTerminalQuery_stmt->
0f310932
AT
519 bind("domain_id", domain_id)->
520 bind("qname", qname)->
521 execute()->
522 reset();
b5baefaf
PD
523 }
524 catch (SSqlException &e) {
2042adf5 525 throw PDNSException("GSQLBackend unable to delete empty non-terminal rr '"+qname.toLogString()+"' from domain_id "+itoa(domain_id)+": "+e.txtReason());
b5baefaf
PD
526 return false;
527 }
528 }
529 }
530
424b92c6 531 for(const auto& qname: insert) {
b5baefaf 532 try {
45d36933
RG
533 reconnectIfNeeded();
534
09070ce7 535 d_InsertEmptyNonTerminalOrderQuery_stmt->
0f310932
AT
536 bind("domain_id", domain_id)->
537 bind("qname", qname)->
09070ce7
PL
538 bindNull("ordername")->
539 bind("auth", true)->
0f310932
AT
540 execute()->
541 reset();
b5baefaf
PD
542 }
543 catch (SSqlException &e) {
2042adf5 544 throw PDNSException("GSQLBackend unable to insert empty non-terminal rr '"+qname.toLogString()+"' in domain_id "+itoa(domain_id)+": "+e.txtReason());
b5baefaf
PD
545 return false;
546 }
547 }
548
549 return true;
550}
551
ece45ffb
PD
552bool GSQLBackend::doesDNSSEC()
553{
554 return d_dnssecQueries;
555}
556
29e0008a 557bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after)
66dba9d7 558{
28f1aab9
BH
559 if(!d_dnssecQueries)
560 return false;
8c1a6d6d 561 after.clear();
8c1a6d6d 562
0f310932 563 SSqlStatement::row_t row;
bb6dd39e 564 try {
45d36933
RG
565 reconnectIfNeeded();
566
0f310932 567 d_afterOrderQuery_stmt->
29e0008a 568 bind("ordername", qname.labelReverse().toString(" ", false))->
0f310932
AT
569 bind("domain_id", id)->
570 execute();
571 while(d_afterOrderQuery_stmt->hasNextRow()) {
572 d_afterOrderQuery_stmt->nextRow(row);
7c779a31 573 ASSERT_ROW_COLUMNS("get-order-after-query", row, 1);
637abecb
KM
574 if(! row[0].empty()) { // Hack because NULL values are passed on as empty strings
575 after=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse();
576 }
0f310932
AT
577 }
578 d_afterOrderQuery_stmt->reset();
bb6dd39e
PD
579 }
580 catch(SSqlException &e) {
63be3701 581 throw PDNSException("GSQLBackend unable to find before/after (after) for domain_id "+itoa(id)+": "+e.txtReason());
bb6dd39e 582 }
66dba9d7 583
29e0008a 584 if(after.empty()) {
bb6dd39e 585 try {
45d36933
RG
586 reconnectIfNeeded();
587
0f310932
AT
588 d_firstOrderQuery_stmt->
589 bind("domain_id", id)->
590 execute();
591 while(d_firstOrderQuery_stmt->hasNextRow()) {
592 d_firstOrderQuery_stmt->nextRow(row);
7c779a31 593 ASSERT_ROW_COLUMNS("get-order-first-query", row, 1);
29e0008a 594 after=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse();
0f310932
AT
595 }
596 d_firstOrderQuery_stmt->reset();
bb6dd39e
PD
597 }
598 catch(SSqlException &e) {
63be3701 599 throw PDNSException("GSQLBackend unable to find before/after (first) for domain_id "+itoa(id)+": "+e.txtReason());
bb6dd39e 600 }
c3c89361
BH
601 }
602
8c1a6d6d
KM
603 if (before.empty()) {
604 unhashed.clear();
bc74a078 605
8c1a6d6d 606 try {
45d36933
RG
607 reconnectIfNeeded();
608
0f310932 609 d_beforeOrderQuery_stmt->
29e0008a 610 bind("ordername", qname.labelReverse().toString(" ", false))->
0f310932
AT
611 bind("domain_id", id)->
612 execute();
613 while(d_beforeOrderQuery_stmt->hasNextRow()) {
614 d_beforeOrderQuery_stmt->nextRow(row);
7c779a31 615 ASSERT_ROW_COLUMNS("get-order-before-query", row, 2);
29e0008a 616 before=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse();
8408d2a6
KM
617 try {
618 unhashed=DNSName(row[1]);
619 } catch (...) {
620 continue;
621 }
0f310932
AT
622 }
623 d_beforeOrderQuery_stmt->reset();
8c1a6d6d
KM
624 }
625 catch(SSqlException &e) {
63be3701 626 throw PDNSException("GSQLBackend unable to find before/after (before) for domain_id "+itoa(id)+": "+e.txtReason());
8c1a6d6d 627 }
8c1a6d6d
KM
628
629 if(! unhashed.empty())
630 {
631 // cerr<<"unhashed="<<unhashed<<",before="<<before<<", after="<<after<<endl;
632 return true;
633 }
634
8c1a6d6d 635 try {
45d36933
RG
636 reconnectIfNeeded();
637
0f310932
AT
638 d_lastOrderQuery_stmt->
639 bind("domain_id", id)->
640 execute();
641 while(d_lastOrderQuery_stmt->hasNextRow()) {
642 d_lastOrderQuery_stmt->nextRow(row);
7c779a31 643 ASSERT_ROW_COLUMNS("get-order-last-query", row, 2);
29e0008a 644 before=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse();
8408d2a6
KM
645 try {
646 unhashed=DNSName(row[1]);
647 } catch (...) {
648 continue;
649 }
0f310932
AT
650 }
651 d_lastOrderQuery_stmt->reset();
8c1a6d6d
KM
652 }
653 catch(SSqlException &e) {
63be3701 654 throw PDNSException("GSQLBackend unable to find before/after (last) for domain_id "+itoa(id)+": "+e.txtReason());
8c1a6d6d 655 }
8c1a6d6d 656 } else {
223d3559 657 before=qname;
66dba9d7
BH
658 }
659
75943e62 660 return true;
66dba9d7
BH
661}
662
82cc0761 663bool GSQLBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id)
c0273500 664{
28f1aab9 665 if(!d_dnssecQueries)
82cc0761 666 return false;
c0273500
BH
667
668 try {
45d36933
RG
669 reconnectIfNeeded();
670
0f310932
AT
671 d_AddDomainKeyQuery_stmt->
672 bind("flags", key.flags)->
673 bind("active", key.active)->
674 bind("content", key.content)->
8f126bc1 675 bind("domain", name)->
0f310932
AT
676 execute()->
677 reset();
c0273500
BH
678 }
679 catch (SSqlException &e) {
63be3701 680 throw PDNSException("GSQLBackend unable to store key: "+e.txtReason());
c0273500 681 }
63de5311
BZ
682
683 try {
45d36933
RG
684 reconnectIfNeeded();
685
63de5311 686 d_GetLastInsertedKeyIdQuery_stmt->execute();
82cc0761
BZ
687 if (!d_GetLastInsertedKeyIdQuery_stmt->hasNextRow()) {
688 id = -2;
689 return true;
690 }
63de5311
BZ
691 SSqlStatement::row_t row;
692 d_GetLastInsertedKeyIdQuery_stmt->nextRow(row);
7b82d9de 693 ASSERT_ROW_COLUMNS("get-last-inserted-key-id-query", row, 1);
82cc0761 694 id = std::stoi(row[0]);
63de5311 695 d_GetLastInsertedKeyIdQuery_stmt->reset();
82cc0761 696 return true;
63de5311
BZ
697 }
698 catch (SSqlException &e) {
82cc0761
BZ
699 id = -2;
700 return true;
63de5311
BZ
701 }
702
82cc0761 703 return false;
c0273500
BH
704}
705
8f126bc1 706bool GSQLBackend::activateDomainKey(const DNSName& name, unsigned int id)
4496f66f 707{
28f1aab9
BH
708 if(!d_dnssecQueries)
709 return false;
4496f66f
BH
710
711 try {
45d36933
RG
712 reconnectIfNeeded();
713
0f310932 714 d_ActivateDomainKeyQuery_stmt->
8f126bc1 715 bind("domain", name)->
0f310932
AT
716 bind("key_id", id)->
717 execute()->
718 reset();
4496f66f
BH
719 }
720 catch (SSqlException &e) {
63be3701 721 throw PDNSException("GSQLBackend unable to activate key: "+e.txtReason());
4496f66f
BH
722 }
723 return true;
724}
725
8f126bc1 726bool GSQLBackend::deactivateDomainKey(const DNSName& name, unsigned int id)
4496f66f 727{
28f1aab9
BH
728 if(!d_dnssecQueries)
729 return false;
4496f66f
BH
730
731 try {
45d36933
RG
732 reconnectIfNeeded();
733
0f310932 734 d_DeactivateDomainKeyQuery_stmt->
8f126bc1 735 bind("domain", name)->
0f310932
AT
736 bind("key_id", id)->
737 execute()->
738 reset();
4496f66f
BH
739 }
740 catch (SSqlException &e) {
63be3701 741 throw PDNSException("GSQLBackend unable to deactivate key: "+e.txtReason());
4496f66f
BH
742 }
743 return true;
744}
745
8f126bc1 746bool GSQLBackend::removeDomainKey(const DNSName& name, unsigned int id)
4496f66f 747{
28f1aab9
BH
748 if(!d_dnssecQueries)
749 return false;
4496f66f
BH
750
751 try {
45d36933
RG
752 reconnectIfNeeded();
753
0f310932 754 d_RemoveDomainKeyQuery_stmt->
8f126bc1 755 bind("domain", name)->
0f310932
AT
756 bind("key_id", id)->
757 execute()->
758 reset();
4496f66f
BH
759 }
760 catch (SSqlException &e) {
63be3701 761 throw PDNSException("GSQLBackend unable to remove key: "+e.txtReason());
4496f66f
BH
762 }
763 return true;
764}
765
8f126bc1 766bool GSQLBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content)
78bcb858 767{
78bcb858 768 try {
45d36933
RG
769 reconnectIfNeeded();
770
0f310932 771 d_getTSIGKeyQuery_stmt->
8f126bc1 772 bind("key_name", name)->
0f310932
AT
773 execute();
774
775 SSqlStatement::row_t row;
776
777 content->clear();
778 while(d_getTSIGKeyQuery_stmt->hasNextRow()) {
779 d_getTSIGKeyQuery_stmt->nextRow(row);
7c779a31 780 ASSERT_ROW_COLUMNS("get-tsig-key-query", row, 2);
8408d2a6
KM
781 try{
782 if(algorithm->empty() || *algorithm==DNSName(row[0])) {
783 *algorithm = DNSName(row[0]);
784 *content = row[1];
785 }
786 } catch (...) {}
0f310932
AT
787 }
788
789 d_getTSIGKeyQuery_stmt->reset();
78bcb858
BH
790 }
791 catch (SSqlException &e) {
63be3701 792 throw PDNSException("GSQLBackend unable to retrieve named TSIG key: "+e.txtReason());
78bcb858 793 }
4496f66f 794
78bcb858
BH
795 return !content->empty();
796}
4496f66f 797
8f126bc1 798bool GSQLBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content)
9a72349d 799{
9a72349d 800 try {
45d36933
RG
801 reconnectIfNeeded();
802
0f310932 803 d_setTSIGKeyQuery_stmt->
8f126bc1
KM
804 bind("key_name", name)->
805 bind("algorithm", algorithm)->
0f310932
AT
806 bind("content", content)->
807 execute()->
808 reset();
9a72349d
AT
809 }
810 catch (SSqlException &e) {
63be3701 811 throw PDNSException("GSQLBackend unable to store named TSIG key: "+e.txtReason());
9a72349d
AT
812 }
813 return true;
814}
815
8f126bc1 816bool GSQLBackend::deleteTSIGKey(const DNSName& name)
9a72349d 817{
9a72349d 818 try {
45d36933
RG
819 reconnectIfNeeded();
820
0f310932 821 d_deleteTSIGKeyQuery_stmt->
8f126bc1 822 bind("key_name", name)->
0f310932
AT
823 execute()->
824 reset();
9a72349d
AT
825 }
826 catch (SSqlException &e) {
63be3701 827 throw PDNSException("GSQLBackend unable to store named TSIG key: "+e.txtReason());
9a72349d
AT
828 }
829 return true;
830}
831
832bool GSQLBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
833{
9a72349d 834 try {
45d36933
RG
835 reconnectIfNeeded();
836
0f310932
AT
837 d_getTSIGKeysQuery_stmt->
838 execute();
839
840 SSqlStatement::row_t row;
841
842 while(d_getTSIGKeysQuery_stmt->hasNextRow()) {
843 d_getTSIGKeysQuery_stmt->nextRow(row);
7c779a31 844 ASSERT_ROW_COLUMNS("get-tsig-keys-query", row, 3);
0f310932 845 struct TSIGKey key;
8408d2a6
KM
846 try {
847 key.name = DNSName(row[0]);
848 key.algorithm = DNSName(row[1]);
849 } catch (...) {
850 continue;
851 }
0f310932
AT
852 key.key = row[2];
853 keys.push_back(key);
854 }
855
856 d_getTSIGKeysQuery_stmt->reset();
9a72349d
AT
857 }
858 catch (SSqlException &e) {
63be3701 859 throw PDNSException("GSQLBackend unable to retrieve TSIG keys: "+e.txtReason());
9a72349d
AT
860 }
861
9a72349d
AT
862 return keys.empty();
863}
864
9c1c5d49 865bool GSQLBackend::getDomainKeys(const DNSName& name, std::vector<KeyData>& keys)
c0273500 866{
28f1aab9
BH
867 if(!d_dnssecQueries)
868 return false;
c0273500
BH
869
870 try {
45d36933
RG
871 reconnectIfNeeded();
872
0f310932 873 d_ListDomainKeysQuery_stmt->
8f126bc1 874 bind("domain", name)->
0f310932
AT
875 execute();
876
877 SSqlStatement::row_t row;
0f310932
AT
878 KeyData kd;
879 while(d_ListDomainKeysQuery_stmt->hasNextRow()) {
880 d_ListDomainKeysQuery_stmt->nextRow(row);
7c779a31 881 ASSERT_ROW_COLUMNS("list-domain-keys-query", row, 4);
424b92c6 882 //~ for(const auto& val: row) {
0f310932
AT
883 //~ cerr<<"'"<<val<<"'"<<endl;
884 //~ }
955e760a
AT
885 kd.id = pdns_stou(row[0]);
886 kd.flags = pdns_stou(row[1]);
887 kd.active = row[2] == "1";
0f310932
AT
888 kd.content = row[3];
889 keys.push_back(kd);
890 }
891
892 d_ListDomainKeysQuery_stmt->reset();
c0273500
BH
893 }
894 catch (SSqlException &e) {
63be3701 895 throw PDNSException("GSQLBackend unable to list keys: "+e.txtReason());
c0273500 896 }
c0273500
BH
897
898 return true;
899}
900
8f126bc1 901void GSQLBackend::alsoNotifies(const DNSName &domain, set<string> *ips)
77151d0b 902{
77151d0b
BH
903 vector<string> meta;
904 getDomainMetadata(domain, "ALSO-NOTIFY", meta);
424b92c6 905 for(const auto& str: meta) {
77151d0b
BH
906 ips->insert(str);
907 }
908}
909
8f126bc1 910bool GSQLBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta)
df0cc941 911{
df0cc941 912 try {
45d36933
RG
913 reconnectIfNeeded();
914
0f310932 915 d_GetAllDomainMetadataQuery_stmt->
8f126bc1 916 bind("domain", name)->
0f310932
AT
917 execute();
918
919 SSqlStatement::row_t row;
920
921 while(d_GetAllDomainMetadataQuery_stmt->hasNextRow()) {
922 d_GetAllDomainMetadataQuery_stmt->nextRow(row);
7c779a31
AT
923 ASSERT_ROW_COLUMNS("get-all-domain-metadata-query", row, 2);
924
0f310932
AT
925 if (!isDnssecDomainMetadata(row[0]))
926 meta[row[0]].push_back(row[1]);
927 }
928
929 d_GetAllDomainMetadataQuery_stmt->reset();
df0cc941
AT
930 }
931 catch (SSqlException &e) {
63be3701 932 throw PDNSException("GSQLBackend unable to list metadata: "+e.txtReason());
df0cc941
AT
933 }
934
df0cc941
AT
935 return true;
936}
937
938
8f126bc1 939bool GSQLBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta)
c0273500 940{
7166723e 941 if(!d_dnssecQueries && isDnssecDomainMetadata(kind))
28f1aab9 942 return false;
7166723e 943
c0273500 944 try {
45d36933
RG
945 reconnectIfNeeded();
946
0f310932 947 d_GetDomainMetadataQuery_stmt->
8f126bc1 948 bind("domain", name)->
0f310932
AT
949 bind("kind", kind)->
950 execute();
951
952 SSqlStatement::row_t row;
953
954 while(d_GetDomainMetadataQuery_stmt->hasNextRow()) {
955 d_GetDomainMetadataQuery_stmt->nextRow(row);
7c779a31 956 ASSERT_ROW_COLUMNS("get-domain-metadata-query", row, 1);
0f310932
AT
957 meta.push_back(row[0]);
958 }
959
960 d_GetDomainMetadataQuery_stmt->reset();
c0273500
BH
961 }
962 catch (SSqlException &e) {
63be3701 963 throw PDNSException("GSQLBackend unable to list metadata: "+e.txtReason());
c0273500 964 }
0f310932 965
c0273500
BH
966 return true;
967}
968
8f126bc1 969bool GSQLBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta)
c0273500 970{
7166723e 971 if(!d_dnssecQueries && isDnssecDomainMetadata(kind))
28f1aab9 972 return false;
f7bcc763 973
c0273500 974 try {
45d36933
RG
975 reconnectIfNeeded();
976
0f310932 977 d_ClearDomainMetadataQuery_stmt->
8f126bc1 978 bind("domain", name)->
0f310932
AT
979 bind("kind", kind)->
980 execute()->
981 reset();
1f93748d 982 if(!meta.empty()) {
424b92c6 983 for(const auto& value: meta) {
0f310932
AT
984 d_SetDomainMetadataQuery_stmt->
985 bind("kind", kind)->
986 bind("content", value)->
8f126bc1 987 bind("domain", name)->
0f310932
AT
988 execute()->
989 reset();
1f93748d
AT
990 }
991 }
c0273500
BH
992 }
993 catch (SSqlException &e) {
63be3701 994 throw PDNSException("GSQLBackend unable to store metadata key: "+e.txtReason());
c0273500 995 }
f7bcc763 996
c0273500
BH
997 return true;
998}
999
f1d06abf 1000void GSQLBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt_p, int domain_id)
b4ce8b4e 1001{
0f310932 1002 try {
45d36933
RG
1003 reconnectIfNeeded();
1004
0f310932
AT
1005 if(qtype.getCode()!=QType::ANY) {
1006 if(domain_id < 0) {
7c779a31 1007 d_query_name = "basic-query";
a59a9c23
AT
1008 d_query_stmt = &d_NoIdQuery_stmt;
1009 (*d_query_stmt)->
0f310932 1010 bind("qtype", qtype.getName())->
8f126bc1 1011 bind("qname", qname);
0f310932 1012 } else {
7c779a31 1013 d_query_name = "id-query";
a59a9c23
AT
1014 d_query_stmt = &d_IdQuery_stmt;
1015 (*d_query_stmt)->
0f310932 1016 bind("qtype", qtype.getName())->
f1d06abf 1017 bind("qname", qname)->
0f310932
AT
1018 bind("domain_id", domain_id);
1019 }
75f02b56 1020 } else {
0f310932
AT
1021 // qtype==ANY
1022 if(domain_id < 0) {
7c779a31 1023 d_query_name = "any-query";
a59a9c23
AT
1024 d_query_stmt = &d_ANYNoIdQuery_stmt;
1025 (*d_query_stmt)->
f1d06abf 1026 bind("qname", qname);
0f310932 1027 } else {
7c779a31 1028 d_query_name = "any-id-query";
a59a9c23
AT
1029 d_query_stmt = &d_ANYIdQuery_stmt;
1030 (*d_query_stmt)->
f1d06abf 1031 bind("qname", qname)->
0f310932
AT
1032 bind("domain_id", domain_id);
1033 }
b4ce8b4e 1034 }
b4ce8b4e 1035
a59a9c23 1036 (*d_query_stmt)->
0f310932 1037 execute();
b4ce8b4e
BH
1038 }
1039 catch(SSqlException &e) {
63be3701 1040 throw PDNSException("GSQLBackend lookup query:"+e.txtReason());
b4ce8b4e
BH
1041 }
1042
1043 d_qname=qname;
b4ce8b4e 1044}
770e6a9c 1045
f1d06abf 1046bool GSQLBackend::list(const DNSName &target, int domain_id, bool include_disabled)
b4ce8b4e 1047{
e6a9dde5 1048 DLOG(g_log<<"GSQLBackend constructing handle for list of domain id '"<<domain_id<<"'"<<endl);
b4ce8b4e 1049
b4ce8b4e 1050 try {
45d36933
RG
1051 reconnectIfNeeded();
1052
7c779a31 1053 d_query_name = "list-query";
a59a9c23
AT
1054 d_query_stmt = &d_listQuery_stmt;
1055 (*d_query_stmt)->
0f310932
AT
1056 bind("include_disabled", (int)include_disabled)->
1057 bind("domain_id", domain_id)->
1058 execute();
b4ce8b4e
BH
1059 }
1060 catch(SSqlException &e) {
63be3701 1061 throw PDNSException("GSQLBackend list query: "+e.txtReason());
b4ce8b4e
BH
1062 }
1063
79de0a80 1064 d_qname.clear();
b4ce8b4e
BH
1065 return true;
1066}
1067
8f126bc1 1068bool GSQLBackend::listSubZone(const DNSName &zone, int domain_id) {
182f7513 1069
2042adf5 1070 string wildzone = "%." + zone.makeLowerCase().toStringNoDot();
0f310932 1071
6a323f63 1072 try {
45d36933
RG
1073 reconnectIfNeeded();
1074
7c779a31 1075 d_query_name = "list-subzone-query";
a59a9c23
AT
1076 d_query_stmt = &d_listSubZoneQuery_stmt;
1077 (*d_query_stmt)->
0f310932
AT
1078 bind("zone", zone)->
1079 bind("wildzone", wildzone)->
1080 bind("domain_id", domain_id)->
1081 execute();
6a323f63
RA
1082 }
1083 catch(SSqlException &e) {
63be3701 1084 throw PDNSException("GSQLBackend listSubZone query: "+e.txtReason());
6a323f63 1085 }
79de0a80 1086 d_qname.clear();
6a323f63
RA
1087 return true;
1088}
1089
0f310932
AT
1090bool GSQLBackend::get(DNSResourceRecord &r)
1091{
e6a9dde5 1092 // g_log << "GSQLBackend get() was called for "<<qtype.getName() << " record: ";
0f310932 1093 SSqlStatement::row_t row;
8408d2a6
KM
1094
1095skiprow:
a59a9c23 1096 if((*d_query_stmt)->hasNextRow()) {
0f310932 1097 try {
a59a9c23 1098 (*d_query_stmt)->nextRow(row);
7c779a31 1099 ASSERT_ROW_COLUMNS(d_query_name, row, 8);
0f310932 1100 } catch (SSqlException &e) {
63be3701 1101 throw PDNSException("GSQLBackend get: "+e.txtReason());
0f310932 1102 }
8408d2a6
KM
1103 try {
1104 extractRecord(row, r);
1105 } catch (...) {
1106 goto skiprow;
1107 }
0f310932
AT
1108 return true;
1109 }
1110
1111 try {
a59a9c23 1112 (*d_query_stmt)->reset();
0f310932 1113 } catch (SSqlException &e) {
63be3701 1114 throw PDNSException("GSQLBackend get: "+e.txtReason());
0f310932
AT
1115 }
1116 d_query_stmt = NULL;
1117 return false;
1118}
6a323f63 1119
223d3559 1120bool GSQLBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **ddb)
b4ce8b4e
BH
1121{
1122 // check if we know the ip/ns couple in the database
1123 for(vector<DNSResourceRecord>::const_iterator i=nsset.begin();i!=nsset.end();++i) {
1124 try {
45d36933
RG
1125 reconnectIfNeeded();
1126
0f310932
AT
1127 d_SuperMasterInfoQuery_stmt->
1128 bind("ip", ip)->
1129 bind("nameserver", i->content)->
1130 execute()->
1131 getResult(d_result)->
1132 reset();
b4ce8b4e
BH
1133 }
1134 catch (SSqlException &e) {
63be3701 1135 throw PDNSException("GSQLBackend unable to search for a domain: "+e.txtReason());
b4ce8b4e 1136 }
b4ce8b4e 1137 if(!d_result.empty()) {
0c55d038 1138 ASSERT_ROW_COLUMNS("supermaster-query", d_result[0], 1);
719f9024 1139 *nameserver=i->content;
b4ce8b4e
BH
1140 *account=d_result[0][0];
1141 *ddb=this;
1142 return true;
1143 }
1144 }
1145 return false;
1146}
1147
aa09fa3b 1148bool GSQLBackend::createDomain(const DNSName &domain, const string &type, const string &masters, const string &account)
487cf033 1149{
487cf033 1150 try {
45d36933
RG
1151 reconnectIfNeeded();
1152
0f310932 1153 d_InsertZoneQuery_stmt->
aa09fa3b 1154 bind("type", type)->
223d3559 1155 bind("domain", domain)->
aa09fa3b
PL
1156 bind("masters", masters)->
1157 bind("account", account)->
0f310932
AT
1158 execute()->
1159 reset();
487cf033
CH
1160 }
1161 catch(SSqlException &e) {
2042adf5 1162 throw PDNSException("Database error trying to insert new domain '"+domain.toLogString()+"': "+ e.txtReason());
487cf033
CH
1163 }
1164 return true;
1165}
1166
223d3559 1167bool GSQLBackend::createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account)
b4ce8b4e 1168{
5805615b 1169 string name;
719f9024 1170 string masters(ip);
b4ce8b4e 1171 try {
719f9024
KM
1172 if (!nameserver.empty()) {
1173 // figure out all IP addresses for the master
45d36933
RG
1174 reconnectIfNeeded();
1175
0f310932
AT
1176 d_GetSuperMasterIPs_stmt->
1177 bind("nameserver", nameserver)->
1178 bind("account", account)->
1179 execute()->
1180 getResult(d_result)->
1181 reset();
5805615b 1182 if (!d_result.empty()) {
d5ebcefe 1183 // collect all IP addresses
5805615b 1184 vector<string> tmp;
424b92c6 1185 for(const auto& row: d_result) {
dd930ede
KM
1186 if (account == row[1])
1187 tmp.push_back(row[0]);
5805615b 1188 }
d5ebcefe 1189 // set them as domain's masters, comma separated
719f9024 1190 masters = boost::join(tmp, ", ");
5805615b 1191 }
719f9024 1192 }
aa09fa3b 1193 createDomain(domain, "SLAVE", masters, account);
b4ce8b4e
BH
1194 }
1195 catch(SSqlException &e) {
2042adf5 1196 throw PDNSException("Database error trying to insert new slave domain '"+domain.toLogString()+"': "+ e.txtReason());
09d6667a
CH
1197 }
1198 return true;
1199}
1200
223d3559 1201bool GSQLBackend::deleteDomain(const DNSName &domain)
09d6667a 1202{
09d6667a
CH
1203 DomainInfo di;
1204 if (!getDomainInfo(domain, di)) {
1205 return false;
1206 }
1207
09d6667a 1208 try {
45d36933
RG
1209 reconnectIfNeeded();
1210
0f310932
AT
1211 d_DeleteZoneQuery_stmt->
1212 bind("domain_id", di.id)->
1213 execute()->
1214 reset();
1215 d_ClearDomainAllMetadataQuery_stmt->
223d3559 1216 bind("domain", domain)->
0f310932
AT
1217 execute()->
1218 reset();
1219 d_ClearDomainAllKeysQuery_stmt->
223d3559 1220 bind("domain", domain)->
0f310932
AT
1221 execute()->
1222 reset();
1223 d_DeleteCommentsQuery_stmt->
1224 bind("domain_id", di.id)->
1225 execute()->
1226 reset();
1227 d_DeleteDomainQuery_stmt->
223d3559 1228 bind("domain", domain)->
0f310932
AT
1229 execute()->
1230 reset();
09d6667a
CH
1231 }
1232 catch(SSqlException &e) {
2042adf5 1233 throw PDNSException("Database error trying to delete domain '"+domain.toLogString()+"': "+ e.txtReason());
b4ce8b4e
BH
1234 }
1235 return true;
1236}
1237
cea26350 1238void GSQLBackend::getAllDomains(vector<DomainInfo> *domains, bool include_disabled)
1325e8a2 1239{
e6a9dde5 1240 DLOG(g_log<<"GSQLBackend retrieving all domains."<<endl);
1325e8a2
PD
1241
1242 try {
45d36933
RG
1243 reconnectIfNeeded();
1244
0f310932
AT
1245 d_getAllDomainsQuery_stmt->
1246 bind("include_disabled", (int)include_disabled)->
1247 execute();
1248
1249 SSqlStatement::row_t row;
1250 while (d_getAllDomainsQuery_stmt->hasNextRow()) {
1251 d_getAllDomainsQuery_stmt->nextRow(row);
7c779a31 1252 ASSERT_ROW_COLUMNS("get-all-domains-query", row, 8);
0f310932 1253 DomainInfo di;
955e760a 1254 di.id = pdns_stou(row[0]);
8408d2a6
KM
1255 try {
1256 di.zone = DNSName(row[1]);
1257 } catch (...) {
1258 continue;
1259 }
0f310932
AT
1260
1261 if (!row[4].empty()) {
d622042f 1262 vector<string> masters;
1263 stringtok(masters, row[4], " ,\t");
1264 for(const auto& m : masters)
1265 di.masters.emplace_back(m, 53);
0f310932 1266 }
8ffb7a9b 1267
0f310932
AT
1268 SOAData sd;
1269 fillSOAData(row[2], sd);
1270 di.serial = sd.serial;
955e760a
AT
1271 di.notified_serial = pdns_stou(row[5]);
1272 di.last_check = pdns_stou(row[6]);
8ffb7a9b
CH
1273 di.account = row[7];
1274
0f310932
AT
1275 if (pdns_iequals(row[3], "MASTER"))
1276 di.kind = DomainInfo::Master;
1277 else if (pdns_iequals(row[3], "SLAVE"))
1278 di.kind = DomainInfo::Slave;
1279 else
1280 di.kind = DomainInfo::Native;
1281
1282 di.backend = this;
1283
1284 domains->push_back(di);
1285 }
1286 d_getAllDomainsQuery_stmt->reset();
1325e8a2
PD
1287 }
1288 catch (SSqlException &e) {
63be3701 1289 throw PDNSException("Database error trying to retrieve all domains:" + e.txtReason());
1325e8a2 1290 }
b4ce8b4e
BH
1291}
1292
8f126bc1 1293bool GSQLBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset)
8bbb6f36 1294{
f374debc 1295 try {
45d36933
RG
1296 reconnectIfNeeded();
1297
0f310932
AT
1298 if (qt != QType::ANY) {
1299 d_DeleteRRSetQuery_stmt->
1300 bind("domain_id", domain_id)->
1301 bind("qname", qname)->
1302 bind("qtype", qt.getName())->
1303 execute()->
1304 reset();
1305 } else {
1306 d_DeleteNamesQuery_stmt->
1307 bind("domain_id", domain_id)->
1308 bind("qname", qname)->
1309 execute()->
1310 reset();
1311 }
f374debc
KM
1312 }
1313 catch (SSqlException &e) {
63be3701 1314 throw PDNSException("GSQLBackend unable to delete RRSet: "+e.txtReason());
f374debc
KM
1315 }
1316
6cc98ddf 1317 if (rrset.empty()) {
f374debc 1318 try {
45d36933
RG
1319 reconnectIfNeeded();
1320
0f310932
AT
1321 d_DeleteCommentRRsetQuery_stmt->
1322 bind("domain_id", domain_id)->
1323 bind("qname", qname)->
1324 bind("qtype", qt.getName())->
1325 execute()->
1326 reset();
f374debc
KM
1327 }
1328 catch (SSqlException &e) {
63be3701 1329 throw PDNSException("GSQLBackend unable to delete comment: "+e.txtReason());
f374debc 1330 }
6cc98ddf 1331 }
424b92c6 1332 for(const auto& rr: rrset) {
c9b43446 1333 feedRecord(rr, DNSName());
8bbb6f36
BH
1334 }
1335
1336 return true;
1337}
1338
c9b43446 1339bool GSQLBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordername)
b4ce8b4e 1340{
b9bafae0
KM
1341 int prio=0;
1342 string content(r.content);
0f310932 1343 if (r.qtype == QType::MX || r.qtype == QType::SRV) {
b9bafae0 1344 string::size_type pos = content.find_first_not_of("0123456789");
955e760a
AT
1345 if (pos != string::npos) {
1346 prio=pdns_stou(content.substr(0,pos));
b9bafae0 1347 boost::erase_head(content, pos);
955e760a 1348 }
b9bafae0 1349 trim_left(content);
0f310932 1350 }
f9cf6d92 1351
b4ce8b4e 1352 try {
45d36933
RG
1353 reconnectIfNeeded();
1354
08536840
PL
1355 d_InsertRecordQuery_stmt->
1356 bind("content",content)->
1357 bind("ttl",r.ttl)->
1358 bind("priority",prio)->
1359 bind("qtype",r.qtype.getName())->
1360 bind("domain_id",r.domain_id)->
1361 bind("disabled",r.disabled)->
f1c083f2 1362 bind("qname",r.qname);
08536840 1363
c9b43446
KM
1364 if (!ordername.empty())
1365 d_InsertRecordQuery_stmt->bind("ordername", ordername.labelReverse().makeLowerCase().toString(" ", false));
0f310932 1366 else
c9b43446 1367 d_InsertRecordQuery_stmt->bindNull("ordername");
08536840
PL
1368
1369 if (d_dnssecQueries)
1370 d_InsertRecordQuery_stmt->bind("auth", r.auth);
1371 else
1372 d_InsertRecordQuery_stmt->bind("auth", true);
1373
1374 d_InsertRecordQuery_stmt->
1375 execute()->
1376 reset();
b4ce8b4e
BH
1377 }
1378 catch (SSqlException &e) {
63be3701 1379 throw PDNSException("GSQLBackend unable to feed record: "+e.txtReason());
b4ce8b4e
BH
1380 }
1381 return true; // XXX FIXME this API should not return 'true' I think -ahu
1382}
1383
223d3559 1384bool GSQLBackend::feedEnts(int domain_id, map<DNSName,bool>& nonterm)
f9cf6d92 1385{
424b92c6 1386 for(const auto& nt: nonterm) {
f9cf6d92 1387 try {
45d36933
RG
1388 reconnectIfNeeded();
1389
09070ce7 1390 d_InsertEmptyNonTerminalOrderQuery_stmt->
0f310932 1391 bind("domain_id",domain_id)->
223d3559 1392 bind("qname", nt.first)->
09070ce7 1393 bindNull("ordername")->
0f310932
AT
1394 bind("auth",(nt.second || !d_dnssecQueries))->
1395 execute()->
424b92c6 1396 reset();
f9cf6d92
KM
1397 }
1398 catch (SSqlException &e) {
63be3701 1399 throw PDNSException("GSQLBackend unable to feed empty non-terminal: "+e.txtReason());
f9cf6d92
KM
1400 }
1401 }
1402 return true;
1403}
1404
28e2e78e 1405bool GSQLBackend::feedEnts3(int domain_id, const DNSName &domain, map<DNSName,bool> &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow)
f9cf6d92
KM
1406{
1407 if(!d_dnssecQueries)
1408 return false;
1409
0f310932 1410 string ordername;
e5c7239c 1411
424b92c6 1412 for(const auto& nt: nonterm) {
f9cf6d92 1413 try {
45d36933
RG
1414 reconnectIfNeeded();
1415
09070ce7
PL
1416 d_InsertEmptyNonTerminalOrderQuery_stmt->
1417 bind("domain_id",domain_id)->
1418 bind("qname", nt.first);
1419 if (narrow || !nt.second) {
1420 d_InsertEmptyNonTerminalOrderQuery_stmt->
1421 bindNull("ordername");
0f310932 1422 } else {
28e2e78e 1423 ordername=toBase32Hex(hashQNameWithSalt(ns3prc, nt.first));
09070ce7
PL
1424 d_InsertEmptyNonTerminalOrderQuery_stmt->
1425 bind("ordername", ordername);
0f310932 1426 }
09070ce7
PL
1427 d_InsertEmptyNonTerminalOrderQuery_stmt->
1428 bind("auth",nt.second)->
1429 execute()->
1430 reset();
f9cf6d92
KM
1431 }
1432 catch (SSqlException &e) {
63be3701 1433 throw PDNSException("GSQLBackend unable to feed empty non-terminal: "+e.txtReason());
f9cf6d92
KM
1434 }
1435 }
1436 return true;
1437}
1438
223d3559 1439bool GSQLBackend::startTransaction(const DNSName &domain, int domain_id)
b4ce8b4e
BH
1440{
1441 try {
45d36933
RG
1442 reconnectIfNeeded();
1443
0f310932 1444 d_db->startTransaction();
bfa196c0 1445 d_inTransaction = true;
0f310932
AT
1446 if(domain_id >= 0) {
1447 d_DeleteZoneQuery_stmt->
1448 bind("domain_id", domain_id)->
1449 execute()->
1450 reset();
1451 }
b4ce8b4e
BH
1452 }
1453 catch (SSqlException &e) {
bfa196c0 1454 d_inTransaction = false;
63be3701 1455 throw PDNSException("Database failed to start transaction: "+e.txtReason());
b4ce8b4e
BH
1456 }
1457
1458 return true;
1459}
1460
1461bool GSQLBackend::commitTransaction()
1462{
1463 try {
0f310932 1464 d_db->commit();
bfa196c0 1465 d_inTransaction = false;
b4ce8b4e
BH
1466 }
1467 catch (SSqlException &e) {
bfa196c0 1468 d_inTransaction = false;
63be3701 1469 throw PDNSException("Database failed to commit transaction: "+e.txtReason());
b4ce8b4e
BH
1470 }
1471 return true;
1472}
1473
1474bool GSQLBackend::abortTransaction()
1475{
1476 try {
0f310932 1477 d_db->rollback();
bfa196c0 1478 d_inTransaction = false;
b4ce8b4e
BH
1479 }
1480 catch(SSqlException &e) {
bfa196c0 1481 d_inTransaction = false;
63be3701 1482 throw PDNSException("Database failed to abort transaction: "+string(e.txtReason()));
b4ce8b4e
BH
1483 }
1484 return true;
1485}
1486
f1013009 1487bool GSQLBackend::calculateSOASerial(const DNSName& domain, const SOAData& sd, uint32_t& serial)
d07fc616
PD
1488{
1489 if (d_ZoneLastChangeQuery.empty()) {
1490 // query not set => fall back to default impl
1491 return DNSBackend::calculateSOASerial(domain, sd, serial);
1492 }
512eafef 1493
d07fc616 1494 try {
45d36933
RG
1495 reconnectIfNeeded();
1496
0f310932
AT
1497 d_ZoneLastChangeQuery_stmt->
1498 bind("domain_id", sd.domain_id)->
1499 execute()->
1500 getResult(d_result)->
1501 reset();
d07fc616
PD
1502 }
1503 catch (const SSqlException& e) {
e6a9dde5 1504 //DLOG(g_log<<"GSQLBackend unable to calculate SOA serial: " << e.txtReason()<<endl);
d07fc616
PD
1505 return false;
1506 }
0f310932
AT
1507
1508 if (!d_result.empty()) {
7c779a31 1509 ASSERT_ROW_COLUMNS("zone-lastchange-query", d_result[0], 1);
955e760a 1510 serial = pdns_stou(d_result[0][0]);
d07fc616
PD
1511 return true;
1512 }
1513
1514 return false;
1515}
6cc98ddf
CH
1516
1517bool GSQLBackend::listComments(const uint32_t domain_id)
1518{
6cc98ddf 1519 try {
45d36933
RG
1520 reconnectIfNeeded();
1521
7c779a31 1522 d_query_name = "list-comments-query";
a59a9c23
AT
1523 d_query_stmt = &d_ListCommentsQuery_stmt;
1524 (*d_query_stmt)->
0f310932
AT
1525 bind("domain_id", domain_id)->
1526 execute();
6cc98ddf
CH
1527 }
1528 catch(SSqlException &e) {
63be3701 1529 throw PDNSException("GSQLBackend list comments query: "+e.txtReason());
6cc98ddf
CH
1530 }
1531
1532 return true;
1533}
1534
1535bool GSQLBackend::getComment(Comment& comment)
1536{
0f310932 1537 SSqlStatement::row_t row;
6cc98ddf 1538
25dcc05f 1539 for(;;) {
a59a9c23 1540 if (!(*d_query_stmt)->hasNextRow()) {
25dcc05f 1541 try {
a59a9c23 1542 (*d_query_stmt)->reset();
25dcc05f 1543 } catch(SSqlException &e) {
63be3701 1544 throw PDNSException("GSQLBackend comment get: "+e.txtReason());
25dcc05f
CH
1545 }
1546 d_query_stmt = NULL;
1547 return false;
1548 }
1549
0f310932 1550 try {
a59a9c23 1551 (*d_query_stmt)->nextRow(row);
25dcc05f 1552 ASSERT_ROW_COLUMNS(d_query_name, row, 6);
0f310932 1553 } catch(SSqlException &e) {
63be3701 1554 throw PDNSException("GSQLBackend comment get: "+e.txtReason());
0f310932 1555 }
25dcc05f
CH
1556 try {
1557 extractComment(row, comment);
1558 } catch (...) {
1559 continue;
1560 }
1561 return true;
0f310932 1562 }
6cc98ddf
CH
1563}
1564
1565void GSQLBackend::feedComment(const Comment& comment)
1566{
6cc98ddf 1567 try {
45d36933
RG
1568 reconnectIfNeeded();
1569
0f310932
AT
1570 d_InsertCommentQuery_stmt->
1571 bind("domain_id",comment.domain_id)->
25dcc05f 1572 bind("qname",comment.qname)->
0f310932
AT
1573 bind("qtype",comment.qtype.getName())->
1574 bind("modified_at",comment.modified_at)->
1575 bind("account",comment.account)->
1576 bind("content",comment.content)->
1577 execute()->
1578 reset();
6cc98ddf
CH
1579 }
1580 catch (SSqlException &e) {
63be3701 1581 throw PDNSException("GSQLBackend unable to feed comment: "+e.txtReason());
6cc98ddf
CH
1582 }
1583}
1584
8f126bc1 1585bool GSQLBackend::replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<Comment>& comments)
6cc98ddf 1586{
f374debc 1587 try {
45d36933
RG
1588 reconnectIfNeeded();
1589
0f310932
AT
1590 d_DeleteCommentRRsetQuery_stmt->
1591 bind("domain_id",domain_id)->
8f126bc1 1592 bind("qname", qname)->
0f310932
AT
1593 bind("qtype",qt.getName())->
1594 execute()->
1595 reset();
f374debc
KM
1596 }
1597 catch (SSqlException &e) {
63be3701 1598 throw PDNSException("GSQLBackend unable to delete comment: "+e.txtReason());
f374debc 1599 }
6cc98ddf 1600
424b92c6 1601 for(const auto& comment: comments) {
6cc98ddf
CH
1602 feedComment(comment);
1603 }
1604
1605 return true;
1606}
0f310932 1607
f641c3b7
PD
1608string GSQLBackend::directBackendCmd(const string &query)
1609{
1610 try {
1611 ostringstream out;
1612
a59a9c23 1613 auto stmt = d_db->prepare(query,0);
f641c3b7 1614
45d36933
RG
1615 reconnectIfNeeded();
1616
f641c3b7
PD
1617 stmt->execute();
1618
1619 SSqlStatement::row_t row;
1620
1621 while(stmt->hasNextRow()) {
1622 stmt->nextRow(row);
424b92c6 1623 for(const auto& col: row)
f641c3b7
PD
1624 out<<"\'"<<col<<"\'\t";
1625 out<<endl;
1626 }
1627
1628 return out.str();
1629 }
1630 catch (SSqlException &e) {
63be3701 1631 throw PDNSException("GSQLBackend unable to execute query: "+e.txtReason());
f641c3b7
PD
1632 }
1633}
1634
474cacfa
AT
1635string GSQLBackend::pattern2SQLPattern(const string &pattern)
1636{
1637 string escaped_pattern = boost::replace_all_copy(pattern,"\\","\\\\");
1638 boost::replace_all(escaped_pattern,"_","\\_");
1639 boost::replace_all(escaped_pattern,"%","\\%");
1640 boost::replace_all(escaped_pattern,"*","%");
1641 boost::replace_all(escaped_pattern,"?","_");
1642 return escaped_pattern;
1643}
1644
1645bool GSQLBackend::searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result)
1646{
25dcc05f 1647 d_qname.clear();
474cacfa
AT
1648 try {
1649 string escaped_pattern = pattern2SQLPattern(pattern);
1650
45d36933
RG
1651 reconnectIfNeeded();
1652
474cacfa
AT
1653 d_SearchRecordsQuery_stmt->
1654 bind("value", escaped_pattern)->
1655 bind("value2", escaped_pattern)->
1656 bind("limit", maxResults)->
1657 execute();
1658
1659 while(d_SearchRecordsQuery_stmt->hasNextRow())
1660 {
1661 SSqlStatement::row_t row;
1662 DNSResourceRecord r;
1663 d_SearchRecordsQuery_stmt->nextRow(row);
7c779a31 1664 ASSERT_ROW_COLUMNS("search-records-query", row, 8);
8408d2a6
KM
1665 try {
1666 extractRecord(row, r);
1667 } catch (...) {
1668 continue;
1669 }
474cacfa
AT
1670 result.push_back(r);
1671 }
1672
1673 d_SearchRecordsQuery_stmt->reset();
1674
1675 return true;
1676 }
1677 catch (SSqlException &e) {
63be3701 1678 throw PDNSException("GSQLBackend unable to execute query: "+e.txtReason());
474cacfa
AT
1679 }
1680
1681 return false;
1682}
1683
1684bool GSQLBackend::searchComments(const string &pattern, int maxResults, vector<Comment>& result)
1685{
1686 Comment c;
1687 try {
1688 string escaped_pattern = pattern2SQLPattern(pattern);
1689
45d36933
RG
1690 reconnectIfNeeded();
1691
474cacfa 1692 d_SearchCommentsQuery_stmt->
0ec0ee4f
AT
1693 bind("value", escaped_pattern)->
1694 bind("value2", escaped_pattern)->
474cacfa
AT
1695 bind("limit", maxResults)->
1696 execute();
1697
1698 while(d_SearchCommentsQuery_stmt->hasNextRow()) {
1699 SSqlStatement::row_t row;
1700 d_SearchCommentsQuery_stmt->nextRow(row);
7c779a31 1701 ASSERT_ROW_COLUMNS("search-comments-query", row, 6);
474cacfa 1702 Comment comment;
512ad04f 1703 extractComment(row, comment);
474cacfa
AT
1704 result.push_back(comment);
1705 }
1706
1707 d_SearchRecordsQuery_stmt->reset();
1708
1709 return true;
1710 }
1711 catch (SSqlException &e) {
63be3701 1712 throw PDNSException("GSQLBackend unable to execute query: "+e.txtReason());
474cacfa
AT
1713 }
1714
1715 return false;
1716}
1717
1718void GSQLBackend::extractRecord(const SSqlStatement::row_t& row, DNSResourceRecord& r)
1719{
1720 if (row[1].empty())
1721 r.ttl = ::arg().asNum( "default-ttl" );
1722 else
955e760a 1723 r.ttl=pdns_stou(row[1]);
474cacfa
AT
1724 if(!d_qname.empty())
1725 r.qname=d_qname;
1726 else
290a083d 1727 r.qname=DNSName(row[6]);
2e9974be 1728
474cacfa
AT
1729 r.qtype=row[3];
1730
e1f36dce 1731 if (r.qtype==QType::MX || r.qtype==QType::SRV)
474cacfa 1732 r.content=row[2]+" "+row[0];
e1f36dce 1733 else
474cacfa
AT
1734 r.content=row[0];
1735
1736 r.last_modified=0;
1737
1738 if(d_dnssecQueries)
1739 r.auth = !row[7].empty() && row[7][0]=='1';
1740 else
1741 r.auth = 1;
1742
1743 r.disabled = !row[5].empty() && row[5][0]=='1';
1744
955e760a 1745 r.domain_id=pdns_stou(row[4]);
474cacfa 1746}
f641c3b7 1747
512ad04f
AT
1748void GSQLBackend::extractComment(const SSqlStatement::row_t& row, Comment& comment)
1749{
25dcc05f
CH
1750 comment.domain_id = pdns_stou(row[0]);
1751 comment.qname = DNSName(row[1]);
1752 comment.qtype = row[2];
1753 comment.modified_at = pdns_stou(row[3]);
1754 comment.account = row[4];
1755 comment.content = row[5];
512ad04f
AT
1756}
1757
0f310932
AT
1758SSqlStatement::~SSqlStatement() {
1759// make sure vtable won't break
1760}