private long getTagId(Tag tag) {
   if (myGetTagIdStatement == null) {
     myGetTagIdStatement =
         myDatabase.compileStatement("SELECT tag_id FROM Tags WHERE parent_id = ? AND name = ?");
     myCreateTagIdStatement =
         myDatabase.compileStatement("INSERT OR IGNORE INTO Tags (parent_id,name) VALUES (?,?)");
   }
   {
     final Long id = myIdByTag.get(tag);
     if (id != null) {
       return id;
     }
   }
   if (tag.Parent != null) {
     myGetTagIdStatement.bindLong(1, getTagId(tag.Parent));
   } else {
     myGetTagIdStatement.bindNull(1);
   }
   myGetTagIdStatement.bindString(2, tag.Name);
   long id;
   try {
     id = myGetTagIdStatement.simpleQueryForLong();
   } catch (SQLException e) {
     if (tag.Parent != null) {
       myCreateTagIdStatement.bindLong(1, getTagId(tag.Parent));
     } else {
       myCreateTagIdStatement.bindNull(1);
     }
     myCreateTagIdStatement.bindString(2, tag.Name);
     id = myCreateTagIdStatement.executeInsert();
   }
   myIdByTag.put(tag, id);
   myTagById.put(id, tag);
   return id;
 }
 protected Collection<FileInfo> loadFileInfos() {
   Cursor cursor = myDatabase.rawQuery("SELECT file_id,name,parent_id,size FROM Files", null);
   HashMap<Long, FileInfo> infosById = new HashMap<Long, FileInfo>();
   while (cursor.moveToNext()) {
     final long id = cursor.getLong(0);
     final FileInfo info =
         createFileInfo(
             id, cursor.getString(1), cursor.isNull(2) ? null : infosById.get(cursor.getLong(2)));
     if (!cursor.isNull(3)) {
       info.FileSize = cursor.getLong(3);
     }
     infosById.put(id, info);
   }
   cursor.close();
   return infosById.values();
 }
 private Tag getTagById(long id) {
   Tag tag = myTagById.get(id);
   if (tag == null) {
     final Cursor cursor =
         myDatabase.rawQuery(
             "SELECT parent_id,name FROM Tags WHERE tag_id = ?", new String[] {"" + id});
     if (cursor.moveToNext()) {
       final Tag parent = cursor.isNull(0) ? null : getTagById(cursor.getLong(0));
       tag = Tag.getTag(parent, cursor.getString(1));
       myIdByTag.put(tag, id);
       myTagById.put(id, tag);
     }
     cursor.close();
   }
   return tag;
 }
  private void initTagCache() {
    if (myTagCacheIsInitialized) {
      return;
    }
    myTagCacheIsInitialized = true;

    Cursor cursor =
        myDatabase.rawQuery("SELECT tag_id,parent_id,name FROM Tags ORDER BY tag_id", null);
    while (cursor.moveToNext()) {
      long id = cursor.getLong(0);
      if (myTagById.get(id) == null) {
        final Tag tag = Tag.getTag(myTagById.get(cursor.getLong(1)), cursor.getString(2));
        myIdByTag.put(tag, id);
        myTagById.put(id, tag);
      }
    }
    cursor.close();
  }
  @Override
  protected Map<Long, Book> loadBooks(FileInfoSet infos, boolean existing) {
    Cursor cursor =
        myDatabase.rawQuery(
            "SELECT book_id,file_id,title,encoding,language FROM Books WHERE `exists` = "
                + (existing ? 1 : 0),
            null);
    final HashMap<Long, Book> booksById = new HashMap<Long, Book>();
    final HashMap<Long, Book> booksByFileId = new HashMap<Long, Book>();
    while (cursor.moveToNext()) {
      final long id = cursor.getLong(0);
      final long fileId = cursor.getLong(1);
      final Book book =
          createBook(
              id,
              infos.getFile(fileId),
              cursor.getString(2),
              cursor.getString(3),
              cursor.getString(4));
      if (book != null) {
        booksById.put(id, book);
        booksByFileId.put(fileId, book);
      }
    }
    cursor.close();

    initTagCache();

    cursor = myDatabase.rawQuery("SELECT author_id,name,sort_key FROM Authors", null);
    final HashMap<Long, Author> authorById = new HashMap<Long, Author>();
    while (cursor.moveToNext()) {
      authorById.put(cursor.getLong(0), new Author(cursor.getString(1), cursor.getString(2)));
    }
    cursor.close();

    cursor =
        myDatabase.rawQuery("SELECT book_id,author_id FROM BookAuthor ORDER BY author_index", null);
    while (cursor.moveToNext()) {
      Book book = booksById.get(cursor.getLong(0));
      if (book != null) {
        Author author = authorById.get(cursor.getLong(1));
        if (author != null) {
          addAuthor(book, author);
        }
      }
    }
    cursor.close();

    cursor = myDatabase.rawQuery("SELECT book_id,tag_id FROM BookTag", null);
    while (cursor.moveToNext()) {
      Book book = booksById.get(cursor.getLong(0));
      if (book != null) {
        addTag(book, getTagById(cursor.getLong(1)));
      }
    }
    cursor.close();

    cursor = myDatabase.rawQuery("SELECT series_id,name FROM Series", null);
    final HashMap<Long, String> seriesById = new HashMap<Long, String>();
    while (cursor.moveToNext()) {
      seriesById.put(cursor.getLong(0), cursor.getString(1));
    }
    cursor.close();

    cursor = myDatabase.rawQuery("SELECT book_id,series_id,book_index FROM BookSeries", null);
    while (cursor.moveToNext()) {
      Book book = booksById.get(cursor.getLong(0));
      if (book != null) {
        final String series = seriesById.get(cursor.getLong(1));
        if (series != null) {
          setSeriesInfo(book, series, cursor.getString(2));
        }
      }
    }
    cursor.close();
    return booksByFileId;
  }