blob: 5652de2cd742c4de7d9ef98a692311bdbf2d643e [file] [log] [blame]
Shock Jiang3016c982014-11-11 11:35:17 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yumin Xia2c509c22017-02-09 14:37:36 -08002/*
Yumin Xia55a7cc42017-05-14 18:43:34 -07003 * Copyright (c) 2014-2018, Regents of the University of California.
Shock Jiang3016c982014-11-11 11:35:17 -08004 *
5 * This file is part of NDNS (Named Data Networking Domain Name Service).
6 * See AUTHORS.md for complete list of NDNS authors and contributors.
7 *
8 * NDNS is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "db-mgr.hpp"
21#include "logger.hpp"
22#include "clients/response.hpp"
23
24#include <iostream>
25#include <fstream>
26
27namespace ndn {
28namespace ndns {
29
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070030NDNS_LOG_INIT("DbMgr")
Shock Jiang3016c982014-11-11 11:35:17 -080031
Yumin Xia2c509c22017-02-09 14:37:36 -080032static const std::string NDNS_SCHEMA = R"VALUE(
33CREATE TABLE IF NOT EXISTS zones (
34 id INTEGER NOT NULL PRIMARY KEY,
35 name blob NOT NULL UNIQUE,
36 ttl integer(10) NOT NULL);
37
38CREATE TABLE IF NOT EXISTS zone_info (
39 zone_id INTEGER NOT NULL,
40 key VARCHAR(10) NOT NULL,
41 value blob NOT NULL,
42 PRIMARY KEY (zone_id, key),
43 FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade);
44
45CREATE TABLE IF NOT EXISTS rrsets (
46 id INTEGER NOT NULL PRIMARY KEY,
47 zone_id integer(10) NOT NULL,
48 label blob NOT NULL,
49 type blob NOT NULL,
50 version blob NOT NULL,
51 ttl integer(10) NOT NULL,
52 data blob NOT NULL,
53 FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade);
54
55CREATE UNIQUE INDEX rrsets_zone_id_label_type_version
56 ON rrsets (zone_id, label, type, version);
57)VALUE";
Shock Jiang3016c982014-11-11 11:35:17 -080058
59DbMgr::DbMgr(const std::string& dbFile/* = DEFAULT_CONFIG_PATH "/" "ndns.db"*/)
60 : m_dbFile(dbFile)
61 , m_conn(0)
62{
63 if (dbFile.empty())
64 m_dbFile = DEFAULT_DATABASE_PATH "/" "ndns.db";
65
66 this->open();
67
68 NDNS_LOG_INFO("open database: " << m_dbFile);
69}
70
71
72DbMgr::~DbMgr()
73{
74 if (m_conn != 0) {
75 this->close();
76 }
77}
78
79void
80DbMgr::open()
81{
82 int res = sqlite3_open_v2(m_dbFile.c_str(), &m_conn,
83 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
84#ifdef DISABLE_SQLITE3_FS_LOCKING
85 "unix-dotfile"
86#else
87 0
88#endif
89 );
90
91 if (res != SQLITE_OK) {
92 NDNS_LOG_FATAL("Cannot open the db file: " << m_dbFile);
Yumin Xia2c509c22017-02-09 14:37:36 -080093 BOOST_THROW_EXCEPTION(ConnectError("Cannot open the db file: " + m_dbFile));
Shock Jiang3016c982014-11-11 11:35:17 -080094 }
95 // ignore any errors from DB creation (command will fail for the existing database, which is ok)
96 sqlite3_exec(m_conn, NDNS_SCHEMA.c_str(), 0, 0, 0);
97}
98
99void
100DbMgr::close()
101{
102 if (m_conn == 0)
103 return;
104
105 int ret = sqlite3_close(m_conn);
106 if (ret != SQLITE_OK) {
107 NDNS_LOG_FATAL("Cannot close the db: " << m_dbFile);
108 }
109 else {
110 m_conn = 0;
111 NDNS_LOG_INFO("Close database: " << m_dbFile);
112 }
113}
114
115void
116DbMgr::clearAllData()
117{
118 const char* sql = "DELETE FROM zones; DELETE FROM rrsets;";
119
120 int rc = sqlite3_exec(m_conn, sql, 0, 0, 0); // sqlite3_step cannot execute multiple SQL statement
121 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800122 BOOST_THROW_EXCEPTION(ExecuteError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800123 }
124
125 NDNS_LOG_INFO("clear all the data in the database: " << m_dbFile);
126}
127
Yumin Xia55a7cc42017-05-14 18:43:34 -0700128
129void
130DbMgr::saveName(const Name& name, sqlite3_stmt* stmt, int iCol, bool isStatic)
131{
132 const Block& wire = name.wireEncode();
133 sqlite3_bind_blob(stmt, iCol, wire.value(), wire.value_size(), isStatic ? SQLITE_STATIC : SQLITE_TRANSIENT);
134}
135
136Name
137DbMgr::restoreName(sqlite3_stmt* stmt, int iCol)
138{
139 Name name;
140
141 const uint8_t* buffer = static_cast<const uint8_t*>(sqlite3_column_blob(stmt, iCol));
142 size_t nBytesLeft = sqlite3_column_bytes(stmt, iCol);
143
144 while (nBytesLeft > 0) {
145 bool hasDecodingSucceeded;
146 name::Component component;
147 std::tie(hasDecodingSucceeded, component) = Block::fromBuffer(buffer, nBytesLeft);
148 if (!hasDecodingSucceeded) {
149 BOOST_THROW_EXCEPTION(Error("Error while decoding name from the database"));
150 }
151 name.append(component);
152 buffer += component.size();
153 nBytesLeft -= component.size();
154 }
155
156 return name;
157}
158
Shock Jiang3016c982014-11-11 11:35:17 -0800159///////////////////////////////////////////////////////////////////////////////////////////////////
160// Zone
161///////////////////////////////////////////////////////////////////////////////////////////////////
162
163void
164DbMgr::insert(Zone& zone)
165{
166 if (zone.getId() > 0)
167 return;
168
169 sqlite3_stmt* stmt;
170 const char* sql = "INSERT INTO zones (name, ttl) VALUES (?, ?)";
171 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
172 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800173 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800174 }
175
Yumin Xia55a7cc42017-05-14 18:43:34 -0700176
177 saveName(zone.getName(), stmt, 1);
Shock Jiang3016c982014-11-11 11:35:17 -0800178 sqlite3_bind_int(stmt, 2, zone.getTtl().count());
179
180 rc = sqlite3_step(stmt);
181 if (rc != SQLITE_DONE) {
182 sqlite3_finalize(stmt);
Yumin Xia2c509c22017-02-09 14:37:36 -0800183 BOOST_THROW_EXCEPTION(ExecuteError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800184 }
185
186 zone.setId(sqlite3_last_insert_rowid(m_conn));
187 sqlite3_finalize(stmt);
188}
189
Yumin Xia2c509c22017-02-09 14:37:36 -0800190void
191DbMgr::setZoneInfo(Zone& zone,
192 const std::string& key,
193 const Block& value)
194{
195 if (zone.getId() == 0) {
196 BOOST_THROW_EXCEPTION(Error("zone has not been initialized"));
197 }
198
199 if (key.length() > 10) {
200 BOOST_THROW_EXCEPTION(Error("key length should not exceed 10"));
201 }
202
203 sqlite3_stmt* stmt;
204 const char* sql = "INSERT OR REPLACE INTO zone_info (zone_id, key, value) VALUES (?, ?, ?)";
205 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
206 if (rc != SQLITE_OK) {
207 BOOST_THROW_EXCEPTION(PrepareError(sql));
208 }
209
210 sqlite3_bind_int(stmt, 1, zone.getId());
211 sqlite3_bind_text(stmt, 2, key.c_str(), key.length(), SQLITE_STATIC);
212 sqlite3_bind_blob(stmt, 3, value.wire(), value.size(), SQLITE_STATIC);
213
214 rc = sqlite3_step(stmt);
215 if (rc != SQLITE_DONE) {
216 sqlite3_finalize(stmt);
217 BOOST_THROW_EXCEPTION(ExecuteError(sql));
218 }
219
220 sqlite3_finalize(stmt);
221}
222
223std::map<std::string, Block>
224DbMgr::getZoneInfo(Zone& zone)
225{
226 using std::string;
227 std::map<string, Block> rtn;
228
229 if (zone.getId() == 0) {
230 find(zone);
231 }
232
233 if (zone.getId() == 0) {
234 BOOST_THROW_EXCEPTION(Error("zone has not been initialized"));
235 }
236
237 sqlite3_stmt* stmt;
238 const char* sql = "SELECT key, value FROM zone_info WHERE zone_id=?";
239 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
240 if (rc != SQLITE_OK) {
241 BOOST_THROW_EXCEPTION(PrepareError(sql));
242 }
243
244 sqlite3_bind_int(stmt, 1, zone.getId());
245
246 while (sqlite3_step(stmt) == SQLITE_ROW) {
247 const char* key = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
248 rtn[string(key)] = Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 1)),
249 sqlite3_column_bytes(stmt, 1));
250 }
251
252 sqlite3_finalize(stmt);
253 return rtn;
254}
255
256
Shock Jiang3016c982014-11-11 11:35:17 -0800257bool
258DbMgr::find(Zone& zone)
259{
260 sqlite3_stmt* stmt;
261 const char* sql = "SELECT id, ttl FROM zones WHERE name=?";
262 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
263 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800264 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800265 }
266
Yumin Xia55a7cc42017-05-14 18:43:34 -0700267 saveName(zone.getName(), stmt, 1);
Shock Jiang3016c982014-11-11 11:35:17 -0800268
269 if (sqlite3_step(stmt) == SQLITE_ROW) {
270 zone.setId(sqlite3_column_int64(stmt, 0));
271 zone.setTtl(time::seconds(sqlite3_column_int(stmt, 1)));
Yumin Xia2c509c22017-02-09 14:37:36 -0800272 }
273 else {
Shock Jiang3016c982014-11-11 11:35:17 -0800274 zone.setId(0);
275 }
276
277 sqlite3_finalize(stmt);
278
279 return zone.getId() != 0;
280}
281
Jiewen Tan870b29b2014-11-17 19:09:49 -0800282std::vector<Zone>
283DbMgr::listZones()
284{
285 sqlite3_stmt* stmt;
286 const char* sql = "SELECT id, name, ttl FROM zones";
287 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
288 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800289 BOOST_THROW_EXCEPTION(PrepareError(sql));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800290 }
291
292 std::vector<Zone> vec;
293
294 while (sqlite3_step(stmt) == SQLITE_ROW) {
295 vec.emplace_back();
296 Zone& zone = vec.back();
297 zone.setId(sqlite3_column_int64(stmt, 0));
298 zone.setTtl(time::seconds(sqlite3_column_int(stmt, 2)));
Yumin Xia55a7cc42017-05-14 18:43:34 -0700299 zone.setName(restoreName(stmt, 1));
Jiewen Tan870b29b2014-11-17 19:09:49 -0800300 }
301 sqlite3_finalize(stmt);
302
303 return vec;
304}
305
Shock Jiang3016c982014-11-11 11:35:17 -0800306void
307DbMgr::remove(Zone& zone)
308{
309 if (zone.getId() == 0)
310 return;
311
312 sqlite3_stmt* stmt;
313 const char* sql = "DELETE FROM zones where id=?";
314 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
315 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800316 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800317 }
318
319 sqlite3_bind_int64(stmt, 1, zone.getId());
320
321 rc = sqlite3_step(stmt);
322 if (rc != SQLITE_DONE) {
323 sqlite3_finalize(stmt);
Yumin Xia2c509c22017-02-09 14:37:36 -0800324 BOOST_THROW_EXCEPTION(ExecuteError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800325 }
326
327 sqlite3_finalize(stmt);
328
329 zone = Zone();
330}
331
332
333///////////////////////////////////////////////////////////////////////////////////////////////////
334// Rrset
335///////////////////////////////////////////////////////////////////////////////////////////////////
336
337void
338DbMgr::insert(Rrset& rrset)
339{
340 if (rrset.getId() != 0)
341 return;
342
343 if (rrset.getZone() == 0) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800344 BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
Shock Jiang3016c982014-11-11 11:35:17 -0800345 }
346
347 if (rrset.getZone()->getId() == 0) {
348 insert(*rrset.getZone());
349 }
350
351 const char* sql =
352 "INSERT INTO rrsets (zone_id, label, type, version, ttl, data)"
353 " VALUES (?, ?, ?, ?, ?, ?)";
354
355 sqlite3_stmt* stmt;
356 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
357 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800358 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800359 }
360
361 sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
362
Yumin Xia55a7cc42017-05-14 18:43:34 -0700363 saveName(rrset.getLabel(), stmt, 2);
Shock Jiang3016c982014-11-11 11:35:17 -0800364 sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);
365 sqlite3_bind_blob(stmt, 4, rrset.getVersion().wire(), rrset.getVersion().size(), SQLITE_STATIC);
366 sqlite3_bind_int64(stmt, 5, rrset.getTtl().count());
367 sqlite3_bind_blob(stmt, 6, rrset.getData().wire(), rrset.getData().size(), SQLITE_STATIC);
368
369 rc = sqlite3_step(stmt);
370 if (rc != SQLITE_DONE) {
371 sqlite3_finalize(stmt);
Yumin Xia2c509c22017-02-09 14:37:36 -0800372 BOOST_THROW_EXCEPTION(ExecuteError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800373 }
374
375 rrset.setId(sqlite3_last_insert_rowid(m_conn));
376 sqlite3_finalize(stmt);
377}
378
379bool
380DbMgr::find(Rrset& rrset)
381{
382 if (rrset.getZone() == 0) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800383 BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
Shock Jiang3016c982014-11-11 11:35:17 -0800384 }
385
386 if (rrset.getZone()->getId() == 0) {
387 bool isFound = find(*rrset.getZone());
388 if (!isFound) {
389 return false;
390 }
391 }
392
393 sqlite3_stmt* stmt;
394 const char* sql =
395 "SELECT id, ttl, version, data FROM rrsets"
396 " WHERE zone_id=? and label=? and type=?";
397 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
398
399 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800400 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800401 }
402
403 sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
404
Yumin Xia55a7cc42017-05-14 18:43:34 -0700405 saveName(rrset.getLabel(), stmt, 2);
406 sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);
407
408 if (sqlite3_step(stmt) == SQLITE_ROW) {
409 rrset.setId(sqlite3_column_int64(stmt, 0));
410 rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
411 rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
412 sqlite3_column_bytes(stmt, 2)));
413 rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
414 sqlite3_column_bytes(stmt, 3)));
415 }
416 else {
417 rrset.setId(0);
418 }
419 sqlite3_finalize(stmt);
420
421 return rrset.getId() != 0;
422}
423
424bool
425DbMgr::findLowerBound(Rrset& rrset)
426{
427 if (rrset.getZone() == 0) {
428 BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
429 }
430
431 if (rrset.getZone()->getId() == 0) {
432 bool isFound = find(*rrset.getZone());
433 if (!isFound) {
434 return false;
435 }
436 }
437
438 sqlite3_stmt* stmt;
439 const char* sql =
440 "SELECT id, ttl, version, data FROM rrsets"
441 " WHERE zone_id=? and label<? and type=? ORDER BY label DESC";
442 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
443
444 if (rc != SQLITE_OK) {
445 BOOST_THROW_EXCEPTION(PrepareError(sql));
446 }
447
448 sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
449
450 saveName(rrset.getLabel(), stmt, 2);
Shock Jiang3016c982014-11-11 11:35:17 -0800451 sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);
452
453 if (sqlite3_step(stmt) == SQLITE_ROW) {
454 rrset.setId(sqlite3_column_int64(stmt, 0));
455 rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
456 rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
457 sqlite3_column_bytes(stmt, 2)));
458 rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
459 sqlite3_column_bytes(stmt, 3)));
Yumin Xia2c509c22017-02-09 14:37:36 -0800460 }
461 else {
Shock Jiang3016c982014-11-11 11:35:17 -0800462 rrset.setId(0);
463 }
464 sqlite3_finalize(stmt);
465
466 return rrset.getId() != 0;
467}
468
469std::vector<Rrset>
470DbMgr::findRrsets(Zone& zone)
471{
472 if (zone.getId() == 0)
473 find(zone);
474
475 if (zone.getId() == 0)
Yumin Xia2c509c22017-02-09 14:37:36 -0800476 BOOST_THROW_EXCEPTION(RrsetError("Attempting to find all the rrsets with a zone does not in the database"));
Shock Jiang3016c982014-11-11 11:35:17 -0800477
478 std::vector<Rrset> vec;
479 sqlite3_stmt* stmt;
480 const char* sql = "SELECT id, ttl, version, data, label, type "
Yumin Xia55a7cc42017-05-14 18:43:34 -0700481 "FROM rrsets where zone_id=? ORDER BY label";
Shock Jiang3016c982014-11-11 11:35:17 -0800482
483 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
484 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800485 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800486 }
487 sqlite3_bind_int64(stmt, 1, zone.getId());
488
489 while (sqlite3_step(stmt) == SQLITE_ROW) {
490 vec.emplace_back(&zone);
491 Rrset& rrset = vec.back();
492
493 rrset.setId(sqlite3_column_int64(stmt, 0));
494 rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
495 rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
496 sqlite3_column_bytes(stmt, 2)));
497 rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
498 sqlite3_column_bytes(stmt, 3)));
Yumin Xia55a7cc42017-05-14 18:43:34 -0700499 rrset.setLabel(restoreName(stmt, 4));
Shock Jiang3016c982014-11-11 11:35:17 -0800500 rrset.setType(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 5)),
501 sqlite3_column_bytes(stmt, 5)));
502 }
503 sqlite3_finalize(stmt);
504
505 return vec;
506}
507
Yumin Xia55a7cc42017-05-14 18:43:34 -0700508void
509DbMgr::removeRrsetsOfZoneByType(Zone& zone, const name::Component& type)
510{
511 if (zone.getId() == 0)
512 find(zone);
513
514 if (zone.getId() == 0)
515 BOOST_THROW_EXCEPTION(RrsetError("Attempting to find all the rrsets with a zone does not in the database"));
516
517 sqlite3_stmt* stmt;
518 const char* sql = "DELETE FROM rrsets WHERE zone_id = ? AND type = ?";
519 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
520
521 if (rc != SQLITE_OK) {
522 BOOST_THROW_EXCEPTION(PrepareError(sql));
523 }
524
525 sqlite3_bind_int64(stmt, 1, zone.getId());
526 sqlite3_bind_blob(stmt, 2, type.wire(), type.size(), SQLITE_STATIC);
527
528 rc = sqlite3_step(stmt);
529 if (rc != SQLITE_DONE) {
530 sqlite3_finalize(stmt);
531 BOOST_THROW_EXCEPTION(ExecuteError(sql));
532 }
533 sqlite3_finalize(stmt);
534}
Shock Jiang3016c982014-11-11 11:35:17 -0800535
536void
537DbMgr::remove(Rrset& rrset)
538{
539 if (rrset.getId() == 0)
Yumin Xia2c509c22017-02-09 14:37:36 -0800540 BOOST_THROW_EXCEPTION(RrsetError("Attempting to remove Rrset that has no assigned id"));
Shock Jiang3016c982014-11-11 11:35:17 -0800541
542 sqlite3_stmt* stmt;
543 const char* sql = "DELETE FROM rrsets WHERE id=?";
544 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
545
546 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800547 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800548 }
549
550 sqlite3_bind_int64(stmt, 1, rrset.getId());
551
552 rc = sqlite3_step(stmt);
553 if (rc != SQLITE_DONE) {
554 sqlite3_finalize(stmt);
Yumin Xia2c509c22017-02-09 14:37:36 -0800555 BOOST_THROW_EXCEPTION(ExecuteError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800556 }
557
558 sqlite3_finalize(stmt);
559
560 rrset = Rrset(rrset.getZone());
561}
562
563void
564DbMgr::update(Rrset& rrset)
565{
566 if (rrset.getId() == 0) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800567 BOOST_THROW_EXCEPTION(RrsetError("Attempting to replace Rrset that has no assigned id"));
Shock Jiang3016c982014-11-11 11:35:17 -0800568 }
569
570 if (rrset.getZone() == 0) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800571 BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
Shock Jiang3016c982014-11-11 11:35:17 -0800572 }
573
574 sqlite3_stmt* stmt;
575 const char* sql = "UPDATE rrsets SET ttl=?, version=?, data=? WHERE id=?";
576 int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
577
578 if (rc != SQLITE_OK) {
Yumin Xia2c509c22017-02-09 14:37:36 -0800579 BOOST_THROW_EXCEPTION(PrepareError(sql));
Shock Jiang3016c982014-11-11 11:35:17 -0800580 }
581
582 sqlite3_bind_int64(stmt, 1, rrset.getTtl().count());
583 sqlite3_bind_blob(stmt, 2, rrset.getVersion().wire(), rrset.getVersion().size(), SQLITE_STATIC);
584 sqlite3_bind_blob(stmt, 3, rrset.getData().wire(), rrset.getData().size(), SQLITE_STATIC);
585 sqlite3_bind_int64(stmt, 4, rrset.getId());
586
587 sqlite3_step(stmt);
588 sqlite3_finalize(stmt);
589}
590
591} // namespace ndns
592} // namespace ndn