blob: 732e9abe949cca0baec3013cb49d815706e7b0d9 [file] [log] [blame]
Shuo Chen7c6b4d72014-03-26 15:20:30 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Regents of the University of California.
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "sqlite-handle.hpp"
8
9namespace repo {
10
11SqliteHandle::SqliteHandle(const string& dbPath)
12 : StorageHandle(STORAGE_METHOD_SQLITE)
13{
14 if (dbPath.empty()) {
15 std::cerr << "Create db file in local location [" << dbPath << "]. " << std::endl
16 << "You can assign the path using -d option" << std::endl;
17 m_dbPath = string("ndn_repo.db");
18 }
19 else {
20 m_dbPath = dbPath + "/ndn_repo.db";
21 }
22 initializeRepo();
23}
24
25void
26SqliteHandle::initializeRepo()
27{
28 char* errMsg = 0;
29 int rc = sqlite3_open(m_dbPath.c_str(), &m_db);
30 if (rc == SQLITE_OK) {
31 sqlite3_exec(m_db, "CREATE TABLE NDN_REPO ("
32 "name BLOB PRIMARY KEY, "
33 "data BLOB, "
34 "parentName BLOB, "
35 "nChildren INTEGER);\n"
36 "CREATE INDEX NdnRepoparentName ON NDN_REPO (parentName)", 0, 0, &errMsg);
37 // Ignore errors (when database already exists, errors are expected)
38 }
39 else {
40 std::cerr << "Database file open failure rc:" << rc << std::endl;
41 throw Error("Database file open failure");
42 }
43
44 Name rootName;
45 string sql = string("SELECT * FROM NDN_REPO WHERE name = ?;");
46
47 sqlite3_stmt* queryStmt = 0;
48
49 rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
50 if (rc == SQLITE_OK) {
51 if (sqlite3_bind_blob(queryStmt, 1, rootName.wireEncode().wire(),
52 rootName.wireEncode().size(), 0) == SQLITE_OK) {
53 rc = sqlite3_step(queryStmt);
54 if (rc == SQLITE_ROW) {
55 std::cerr << "root has been created" << std::endl;
56 }
57 else if (rc == SQLITE_DONE) {
58 sqlite3_stmt* p2Stmt = 0;
59 sql = string("INSERT INTO NDN_REPO (name, data, parentName, nChildren) "
60 " VALUES (?, ?, ?, ?);");
61 rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &p2Stmt, 0);
62 if (rc == SQLITE_OK) {
63 if (sqlite3_bind_blob(p2Stmt, 1, rootName.wireEncode().wire(),
64 rootName.wireEncode().size(), 0) == SQLITE_OK &&
65 sqlite3_bind_null(p2Stmt, 2) == SQLITE_OK &&
66 sqlite3_bind_null(p2Stmt, 3) == SQLITE_OK &&
67 sqlite3_bind_int(p2Stmt, 4, 0) == SQLITE_OK) {
68 rc = sqlite3_step(p2Stmt);;
69 if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
70 std::cerr << "Root name insert failure rc:" << rc << std::endl;
71 sqlite3_finalize(p2Stmt);
72 throw Error("Root name insert failure");
73 }
74 }
75 else {
76 std::cerr << "bind blob failure rc:" << rc << std::endl;
77 sqlite3_finalize(p2Stmt);
78 throw Error("bind blob failure");
79 }
80 }
81 else {
82 std::cerr << "p2Stmt prepared rc:" << rc << std::endl;
83 sqlite3_finalize(p2Stmt);
84 throw Error("p2Stmt prepared");
85 }
86 sqlite3_finalize(p2Stmt);
87 }
88 else {
89 std::cerr << "Database query failure rc:" << rc << std::endl;
90 sqlite3_finalize(queryStmt);
91 throw Error("Database query failure");
92 }
93 }
94 sqlite3_finalize(queryStmt);
95 }
96 sqlite3_exec(m_db, "PRAGMA synchronous = OFF", 0, 0, &errMsg);
97 sqlite3_exec(m_db, "PRAGMA journal_mode = WAL", 0, 0, &errMsg);
98}
99
100SqliteHandle::~SqliteHandle()
101{
102 sqlite3_close(m_db);
103}
104
105
106//Temporarily assigned the datatype of every component. needs to be further discussed
107
108bool
109SqliteHandle::insertData(const Data& data)
110{
111 Name name = data.getName();
112
113 if (name.empty()) {
114 std::cerr << "name is empty" << std::endl;
115 return false;
116 }
117
118 int rc = 0;
119
120 string updateSql2 = string("UPDATE NDN_REPO SET data = ? WHERE name = ?;");
121 //std::cerr << "update" << std::endl;
122 sqlite3_stmt* update2Stmt = 0;
123 if (sqlite3_prepare_v2(m_db, updateSql2.c_str(), -1, &update2Stmt, 0) != SQLITE_OK) {
124 sqlite3_finalize(update2Stmt);
125 std::cerr << "update sql2 not prepared" << std::endl;
126 throw Error("update sql2 not prepared");
127 }
128 if (sqlite3_bind_blob(update2Stmt, 1,
129 data.wireEncode().wire(),
130 data.wireEncode().size(), 0) == SQLITE_OK &&
131 sqlite3_bind_blob(update2Stmt, 2,
132 name.wireEncode().wire(),
133 name.wireEncode().size(), 0) == SQLITE_OK) {
134 rc = sqlite3_step(update2Stmt);
135 sqlite3_finalize(update2Stmt);
136 if (rc != SQLITE_DONE) {
137 return false;
138 }
139 //what error??
140 //std::cerr << "update rc:" << rc << std::endl;
141 /// \todo Do something with rc
142 }
143 int changeCount = sqlite3_changes(m_db);
144 //std::cerr << "changeCount: " << changeCount << std::endl;
145 if (changeCount > 0) {
146 return true;
147 }
148
149 sqlite3_stmt* insertStmt = 0;
150 sqlite3_stmt* updateStmt = 0;
151 string insertSql = string("INSERT INTO NDN_REPO (name, data, parentName, nChildren) "
152 "VALUES (?, ?, ?, ?)");
153 string updateSql = string("UPDATE NDN_REPO SET nChildren = nChildren + 1 WHERE name = ?");
154
155 Name rootName;
156
157
158 if (sqlite3_prepare_v2(m_db, insertSql.c_str(), -1, &insertStmt, 0) != SQLITE_OK) {
159 sqlite3_finalize(insertStmt);
160 std::cerr << "insert sql not prepared" << std::endl;
161 }
162 if (sqlite3_prepare_v2(m_db, updateSql.c_str(), -1, &updateStmt, 0) != SQLITE_OK) {
163 sqlite3_finalize(updateStmt);
164 std::cerr << "update sql not prepared" << std::endl;
165 throw Error("update sql not prepared");
166 }
167
168 //Insert and read the prefix
169 Name parentName = name;
170 Name grandName;
171 do {
172 parentName = parentName.getPrefix(-1);
173 if (!hasName(parentName)) {
174 grandName = parentName.getPrefix(-1);
175 if (sqlite3_bind_blob(insertStmt, 1,
176 parentName.wireEncode().wire(),
177 parentName.wireEncode().size(), 0) == SQLITE_OK &&
178 sqlite3_bind_null(insertStmt, 2) == SQLITE_OK &&
179 sqlite3_bind_blob(insertStmt, 3,
180 grandName.wireEncode().wire(),
181 grandName.wireEncode().size(), 0) == SQLITE_OK &&
182 sqlite3_bind_int(insertStmt, 4, 1) == SQLITE_OK) {
183 rc = sqlite3_step(insertStmt);
184 if (rc == SQLITE_CONSTRAINT) {
185 std::cerr << "Insert parent prefix failed" << std::endl;
186 sqlite3_finalize(insertStmt);
187 throw Error("Insert parent prefix failed");
188 }
189 sqlite3_reset(insertStmt);
190 }
191 }
192 else {
193 break;
194 }
195 } while (!parentName.empty());
196
197 //The existed parent nChildren + 1
198
199 if (sqlite3_bind_blob(updateStmt, 1, parentName.wireEncode().wire(),
200 parentName.wireEncode().size(), 0) == SQLITE_OK) {
201 rc = sqlite3_step(updateStmt);
202 if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
203 std::cerr << "update error rc:" << rc << std::endl;
204 sqlite3_finalize(updateStmt);
205 sqlite3_finalize(insertStmt);
206 throw Error("update error");
207 }
208 sqlite3_reset(updateStmt);
209 }
210
211 //Insert the name and the data, if this data name exists update, else insert data
212
213 parentName = name.getPrefix(-1);
214 sqlite3_reset(insertStmt);
215 if (sqlite3_bind_blob(insertStmt, 1,
216 name.wireEncode().wire(),
217 name.wireEncode().size(), 0) == SQLITE_OK &&
218 sqlite3_bind_blob(insertStmt, 2,
219 data.wireEncode().wire(),
220 data.wireEncode().size(), 0) == SQLITE_OK &&
221 sqlite3_bind_blob(insertStmt, 3,
222 parentName.wireEncode().wire(),
223 parentName.wireEncode().size(), 0) == SQLITE_OK &&
224 sqlite3_bind_int(insertStmt, 4, 0) == SQLITE_OK) {
225 rc = sqlite3_step(insertStmt);
226 //std::cerr << "insert rc:" << rc << std::endl;
227 //std::cerr << "insert the data: " << data.wireEncode().wire() << std::endl;
228 if (rc == SQLITE_CONSTRAINT) {
229 std::cerr << "The name of the data has existed!" << std::endl;
230 sqlite3_finalize(insertStmt);
231 return false;
232 }
233 }
234
235 sqlite3_finalize(updateStmt);
236 sqlite3_finalize(insertStmt);
237 return true;
238}
239
240bool
241SqliteHandle::deleteData(const Name& name)
242{
243 sqlite3_stmt* queryStmt = 0;
244 sqlite3_stmt* deleteStmt = 0;
245 sqlite3_stmt* updateStmt = 0;
246 sqlite3_stmt* update2Stmt = 0;
247
248 string querySql = string("SELECT * from NDN_REPO where name = ?;");
249 string deleteSql = string("DELETE from NDN_REPO where name = ?;");
250
251 string updateSql = string("UPDATE NDN_REPO SET nChildren = nChildren - 1 WHERE name = ?;");
252 string updateSql2 = string("UPDATE NDN_REPO SET data = NULL WHERE name = ?;");
253
254 int rc = sqlite3_prepare_v2(m_db, querySql.c_str(), -1, &queryStmt, 0);
255 Name tmpName = name;
256 int nChildren = -1;
257 if (sqlite3_prepare_v2(m_db, deleteSql.c_str(), -1, &deleteStmt, 0) != SQLITE_OK) {
258 sqlite3_finalize(deleteStmt);
259 std::cerr << "delete statement prepared failed" << std::endl;
260 throw Error("delete statement prepared failed");
261 }
262 if (sqlite3_prepare_v2(m_db, updateSql.c_str(), -1, &updateStmt, 0) != SQLITE_OK) {
263 sqlite3_finalize(updateStmt);
264 std::cerr << "delete update prepared failed" << std::endl;
265 throw Error("delete update prepared failed");
266 }
267 if (rc == SQLITE_OK) {
268 if (sqlite3_bind_blob(queryStmt, 1,
269 tmpName.wireEncode().wire(),
270 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
271 rc = sqlite3_step(queryStmt);
272 if (rc == SQLITE_ROW) {
273 nChildren = sqlite3_column_int(queryStmt, 3);
274 }
275 else {
276 std::cerr << "Database query no such name or failure rc:" << rc << std::endl;
277 sqlite3_finalize(queryStmt);
278 return false;
279 }
280 }
281 if (nChildren > 0) {
282 //update internal node, so just update and return
283 if (sqlite3_prepare_v2(m_db, updateSql2.c_str(), -1, &update2Stmt, 0) != SQLITE_OK) {
284 sqlite3_finalize(update2Stmt);
285 std::cerr << "delete update prepared failed" << std::endl;
286 throw Error("delete update prepared failed");
287 }
288 if (sqlite3_bind_blob(update2Stmt, 1,
289 tmpName.wireEncode().wire(),
290 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
291 rc = sqlite3_step(update2Stmt);
292 std::cerr << "deleteData update" << std::endl;
293 }
294 else {
295 std::cerr << "delete bind error" << std::endl;
296 sqlite3_finalize(update2Stmt);
297 throw Error("delete bind error");
298 }
299 return true;
300 }
301 else {
302 //Delete the leaf node
303 if (sqlite3_bind_blob(deleteStmt, 1,
304 tmpName.wireEncode().wire(),
305 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
306 rc = sqlite3_step(deleteStmt);
307 if (rc != SQLITE_DONE && rc !=SQLITE_ROW) {
308 std::cerr << "leaf node delete error rc:" << rc << std::endl;
309 sqlite3_finalize(deleteStmt);
310 throw Error("leaf node delete error");
311 }
312 }
313 else {
314 std::cerr << "delete bind error" << std::endl;
315 sqlite3_finalize(deleteStmt);
316 throw Error("delete bind error");
317 }
318 sqlite3_reset(deleteStmt);
319 }
320 queryStmt = 0;
321 rc = sqlite3_prepare_v2(m_db, querySql.c_str(), -1, &queryStmt, 0);
322 if (rc != SQLITE_OK) {
323 std::cerr << "prepare error" << std::endl;
324 sqlite3_finalize(queryStmt);
325 throw Error("prepare error");
326 }
327 //read prefix if nChildren is 0 and data is 0
328 int dataSize = 0;
329 do {
330 tmpName = tmpName.getPrefix(-1);
331 if (sqlite3_bind_blob(queryStmt, 1,
332 tmpName.wireEncode().wire(),
333 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
334 rc = sqlite3_step(queryStmt);
335 if (rc == SQLITE_ROW) {
336 nChildren = sqlite3_column_int(queryStmt, 3);
337 dataSize = sqlite3_column_bytes(queryStmt, 1);
338 }
339 else {
340 std::cerr << "Database query no such name or failure rc:" << rc << std::endl;
341 sqlite3_finalize(queryStmt);
342 return false;
343 }
344 if (nChildren == 1 && !tmpName.empty() && dataSize == 0) {
345 //Delete this internal node
346 if (sqlite3_bind_blob(deleteStmt, 1,
347 tmpName.wireEncode().wire(),
348 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
349 rc = sqlite3_step(deleteStmt);
350 if (rc != SQLITE_DONE && rc !=SQLITE_ROW) {
351 std::cerr << "internal node delete error rc:" << rc << std::endl;
352 sqlite3_finalize(deleteStmt);
353 throw Error("internal node delete error");
354 }
355 }
356 else {
357 std::cerr << "delete bind error" << std::endl;
358 sqlite3_finalize(deleteStmt);
359 throw Error("delete bind error");
360 }
361 sqlite3_reset(deleteStmt);
362 }
363 else {
364 //nChildren - 1
365 if (sqlite3_bind_blob(updateStmt, 1,
366 tmpName.wireEncode().wire(),
367 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
368 rc = sqlite3_step(updateStmt);
369 if (rc != SQLITE_DONE && rc !=SQLITE_ROW) {
370 std::cerr << "internal node nChildren update error rc:" << rc << std::endl;
371 sqlite3_finalize(updateStmt);
372 throw Error("internal node nChildren update error");
373 }
374 }
375 else {
376 std::cerr << "update bind error" << std::endl;
377 sqlite3_finalize(updateStmt);
378 throw Error("update bind error");
379 }
380 sqlite3_reset(updateStmt);
381 break;
382 }
383 }
384 else {
385 std::cerr << "query bind error" << std::endl;
386 sqlite3_finalize(queryStmt);
387 throw Error("query bind error");
388 }
389 sqlite3_reset(queryStmt);
390 } while (!tmpName.empty());
391
392 }
393 else {
394 std::cerr << "query prepared failure rc:" << rc << std::endl;
395 sqlite3_finalize(queryStmt);
396 throw Error("query prepared failure");
397 }
398 return true;
399}
400
401bool
402SqliteHandle::readData(const Interest& interest, Data& data)
403{
404 vector<Name> names;
405 Name resultName;
406 if (!interest.hasSelectors()) {
407 return readDataPlain(interest.getName(), data);
408 }
409 else {
410 if (readNameSelector(interest, names)) {
411 if (!filterNameChild(interest.getName(), interest.getChildSelector(), names, resultName)) {
412 return false;
413 }
414 }
415 return readData(resultName, data);
416 }
417}
418
419// This function is the first version of data read following longest prefix match.
420// It will return the leftmost data
421bool
422SqliteHandle::readDataPlain(const Name& name, Data& data)
423{
424 vector<Name> names;
425 Name resultName;
426 readDataName(name, names);
427 filterNameChild(name, 0, names, resultName);
428 if (!resultName.empty()) {
429 return readData(resultName, data);
430 }
431 else
432 {
433 return false;
434 }
435}
436
437// retrieve all the leaf nodes of a subtree
438bool
439SqliteHandle::readDataName(const Name& name, vector<Name>& names) const
440{
441 if (name.empty()) {
442 std::cerr << "The name is empty" << std::endl;
443 return false;
444 }
445 Name tmpName = name;
446 //This queue is for internal node;
447 queue<Name> internalNames;
448
449 // Step 1. Check if the requested name corresponds to a leaf (data is not NULL)
450 string sql = string("SELECT * FROM NDN_REPO WHERE name = ? AND data IS NOT NULL;");
451 sqlite3_stmt* queryStmt = 0;
452 int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
453 if (rc != SQLITE_OK)
454 throw Error("prepare error");
455
456 if (sqlite3_bind_blob(queryStmt, 1,
457 tmpName.wireEncode().wire(),
458 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
459 rc = sqlite3_step(queryStmt);
460 if (rc == SQLITE_ROW) {
461 int nChildren = sqlite3_column_int(queryStmt, 3);
462 Name elementName;
463 elementName.wireDecode(Block(sqlite3_column_blob(queryStmt, 0),
464 sqlite3_column_bytes(queryStmt, 0)));
465 names.push_back(elementName);
466 if (nChildren == 0) {
467 sqlite3_finalize(queryStmt);
468 return true;
469 }
470 }
471 else if (rc == SQLITE_DONE) {
472 // ignore
473 }
474 else {
475 std::cerr << "read error rc:" << rc << std::endl;
476 sqlite3_finalize(queryStmt);
477 throw Error("read error");
478 }
479 }
480 sqlite3_finalize(queryStmt);
481
482
483 // Step 2. Recursively find all data packets with the specified prefix
484 string psql = string("SELECT * FROM NDN_REPO WHERE parentName = ?;");
485 sqlite3_stmt* queryParentStmt = 0;
486 rc = sqlite3_prepare_v2(m_db, psql.c_str(), -1, &queryParentStmt, 0);
487 if (rc != SQLITE_OK)
488 throw Error("prepare error");
489
490 internalNames.push(tmpName);
491 while (!internalNames.empty()) {
492 tmpName = internalNames.front();
493 internalNames.pop();
494 if (sqlite3_bind_blob(queryParentStmt, 1,
495 tmpName.wireEncode().wire(),
496 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
497 while (true) {
498 rc = sqlite3_step(queryParentStmt);
499 if (rc == SQLITE_ROW) {
500 Name elementName;
501 elementName.wireDecode(Block(sqlite3_column_blob(queryParentStmt, 0),
502 sqlite3_column_bytes(queryParentStmt, 0)));
503 int nChildren = sqlite3_column_int(queryParentStmt, 3);
504 if (nChildren > 0) {
505 internalNames.push(elementName);
506 }
507 if (sqlite3_column_type(queryParentStmt, 3) != SQLITE_NULL) {
508 names.push_back(elementName);
509 }
510 }
511 else if (rc == SQLITE_DONE) {
512 break;
513 }
514 else {
515 std::cerr << "read error rc:" << rc << std::endl;
516 sqlite3_finalize(queryParentStmt);
517 throw Error("read error");
518 }
519 }
520 sqlite3_reset(queryParentStmt);
521 }
522 else {
523 std::cerr << "bind error" << std::endl;
524 sqlite3_finalize(queryParentStmt);
525 throw Error("bind error");
526 }
527 }
528 sqlite3_finalize(queryParentStmt);
529 return true;
530}
531
532bool
533SqliteHandle::readNameSelector(const Interest& interest, vector<Name>& names) const
534{
535 if (interest.getName().empty()) {
536 std::cerr << "The name of interest is empty" << std::endl;
537 return false;
538 }
539 Name tmpName = interest.getName();
540 //This queue is for internal node;
541 queue<Name> internalNames;
542
543 // Step 1. Check if the requested Data corresponds to a leaf (data is not NULL)
544 sqlite3_stmt* queryStmt = 0;
545 string sql = string("SELECT * FROM NDN_REPO WHERE name = ? AND data IS NOT NULL;");
546 int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
547 if (rc != SQLITE_OK)
548 throw Error("prepare error");
549
550 if (sqlite3_bind_blob(queryStmt, 1,
551 tmpName.wireEncode().wire(),
552 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
553 rc = sqlite3_step(queryStmt);
554 if (rc == SQLITE_ROW) {
555 Data elementData;
556 elementData.wireDecode(Block(sqlite3_column_blob(queryStmt, 1),
557 sqlite3_column_bytes(queryStmt, 1)));
558 if (interest.matchesData(elementData)) {
559 names.push_back(elementData.getName());
560 }
561
562 int nChildren = sqlite3_column_int(queryStmt, 3);
563 if (nChildren == 0) {
564 sqlite3_finalize(queryStmt);
565 return true;
566 }
567 }
568 else if (rc == SQLITE_DONE) {
569 // ignore
570 }
571 else {
572 std::cerr << "read error rc:" << rc << std::endl;
573 sqlite3_finalize(queryStmt);
574 throw Error("read error");
575 }
576 }
577 sqlite3_finalize(queryStmt);
578
579 // Step 2. Recursively find all data packets that match the Interest
580 internalNames.push(tmpName);
581 sqlite3_stmt* queryParentStmt = 0;
582 string psql = string("SELECT * FROM NDN_REPO WHERE parentName = ?;");
583 rc = sqlite3_prepare_v2(m_db, psql.c_str(), -1, &queryParentStmt, 0);
584 if (rc != SQLITE_OK)
585 throw Error("prepare error");
586
587 while (!internalNames.empty()) {
588 tmpName = internalNames.front();
589 internalNames.pop();
590 if (sqlite3_bind_blob(queryParentStmt, 1,
591 tmpName.wireEncode().wire(),
592 tmpName.wireEncode().size(), 0) == SQLITE_OK) {
593 while (true) {
594 rc = sqlite3_step(queryParentStmt);
595 if (rc == SQLITE_ROW) {
596 if (sqlite3_column_type(queryParentStmt, 1) != SQLITE_NULL) {
597 Data elementData;
598 elementData.wireDecode(Block(sqlite3_column_blob(queryParentStmt, 1),
599 sqlite3_column_bytes(queryParentStmt, 1)));
600 if (interest.matchesData(elementData)) {
601 names.push_back(elementData.getName());
602 }
603 }
604
605 Name elementName;
606 elementName.wireDecode(Block(sqlite3_column_blob(queryParentStmt, 0),
607 sqlite3_column_bytes(queryParentStmt, 0)));
608
609 int nChildren = sqlite3_column_int(queryParentStmt, 3);
610 if (nChildren > 0) {
611 internalNames.push(elementName);
612 }
613 }
614 else if (rc == SQLITE_DONE) {
615 break;
616 }
617 else {
618 std::cerr << "read error rc:" << rc << std::endl;
619 sqlite3_finalize(queryParentStmt);
620 throw Error("read error");
621 }
622 }
623 sqlite3_reset(queryParentStmt);
624 }
625 else {
626 std::cerr << "bind error" << std::endl;
627 sqlite3_finalize(queryParentStmt);
628 throw Error("bind error");
629 }
630 }
631 sqlite3_finalize(queryParentStmt);
632 return true;
633}
634
635bool
636SqliteHandle::filterNameChild(const Name& name, int childSelector,
637 const vector<Name>& names, Name& resultName)
638{
639 if (childSelector == 0) {
640 if (!names.empty()) {
641 resultName = *std::min_element(names.begin(), names.end());
642 }
643 else {
644 return false;
645 }
646 }
647 else if (childSelector == 1) {
648 if (!names.empty()) {
649 resultName = *std::max_element(names.begin(), names.end());
650 }
651 else {
652 return false;
653 }
654 }
655 else {
656 return false;
657 }
658 return true;
659}
660
661bool
662SqliteHandle::readNameAny(const Name& name, const Selectors& selectors, vector<Name>& names)
663{
664 if (selectors.empty()) {
665 if (hasName(name)) {
666 names.push_back(name);
667 }
668 return true;
669 }
670 else {
671 Interest interest(name);
672 interest.setSelectors(selectors);
673 readNameSelector(interest, names);
674 if (selectors.getChildSelector() >= 0) {
675 Name resultName;
676 if (!filterNameChild(name, selectors.getChildSelector(), names, resultName))
677 return false;
678 names.clear();
679 names.push_back(resultName);
680 return true;
681 }
682 else {
683 return true;
684 }
685 }
686}
687
688bool
689SqliteHandle::readData(const Name& name, Data& data)
690{
691 sqlite3_stmt* queryStmt = 0;
692 string sql = string("SELECT * FROM NDN_REPO WHERE name = ? AND data IS NOT NULL;");
693 int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
694 if (rc == SQLITE_OK) {
695 if (sqlite3_bind_blob(queryStmt, 1,
696 name.wireEncode().wire(),
697 name.wireEncode().size(), 0) == SQLITE_OK) {
698 rc = sqlite3_step(queryStmt);
699 if (rc == SQLITE_ROW) {
700 data.wireDecode(Block(sqlite3_column_blob(queryStmt, 1),
701 sqlite3_column_bytes(queryStmt, 1)));
702 sqlite3_finalize(queryStmt);
703 return true;
704 }
705 else if (rc == SQLITE_DONE) {
706 return false;
707 }
708 else {
709 std::cerr << "Database query failure rc:" << rc << std::endl;
710 sqlite3_finalize(queryStmt);
711 throw Error("Database query failure");
712 }
713 }
714 sqlite3_finalize(queryStmt);
715 }
716 return true;
717}
718
719
720//This is the exact name query in database.
721bool
722SqliteHandle::hasName(const Name& name)
723{
724 sqlite3_stmt* queryStmt = 0;
725 string sql = string("select * from NDN_REPO where name = ?;");
726 int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
727 if (rc == SQLITE_OK) {
728 if (sqlite3_bind_blob(queryStmt, 1,
729 name.wireEncode().wire(),
730 name.wireEncode().size(), 0) == SQLITE_OK) {
731 rc = sqlite3_step(queryStmt);
732 if (rc == SQLITE_ROW) {
733 sqlite3_finalize(queryStmt);
734 return true;
735 }
736 else if (rc == SQLITE_DONE) {
737 sqlite3_finalize(queryStmt);
738 return false;
739 }
740 else {
741 std::cerr << "Database query failure rc:" << rc << std::endl;
742 sqlite3_finalize(queryStmt);
743 return false;
744 }
745 }
746 sqlite3_finalize(queryStmt);
747 }
748 return true;
749}
750
751//This is the exact parent name query in database.
752bool
753SqliteHandle::hasParentName(const Name& parentName) const
754{
755 sqlite3_stmt* queryStmt = 0;
756 string sql = string("SELECT * FROM NDN_REPO WHERE parentName = ?;");
757 int rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &queryStmt, 0);
758 if (rc == SQLITE_OK) {
759 if (sqlite3_bind_blob(queryStmt, 1,
760 parentName.wireEncode().wire(),
761 parentName.wireEncode().size(), 0) == SQLITE_OK) {
762 rc = sqlite3_step(queryStmt);
763 if (rc == SQLITE_ROW) {
764 sqlite3_finalize(queryStmt);
765 return true;
766 }
767 else if (rc == SQLITE_DONE) {
768 sqlite3_finalize(queryStmt);
769 return false;
770 }
771 else {
772 std::cerr << "Database query failure rc:" << rc << std::endl;
773 sqlite3_finalize(queryStmt);
774 return false;
775 }
776 }
777 sqlite3_finalize(queryStmt);
778 }
779 return true;
780}
781
782} //namespace repo