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