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