/** {@inheritDoc} */
 @Override
 public JobHolder nextJobAndIncRunCount(@NonNull Constraint constraint) {
   final Where where = createWhere(constraint);
   // we can even keep these prepared but not sure the cost of them in db layer
   final String selectQuery = where.nextJob(sqlHelper);
   while (true) {
     Cursor cursor = db.rawQuery(selectQuery, where.args);
     try {
       if (!cursor.moveToNext()) {
         return null;
       }
       JobHolder holder = createJobHolderFromCursor(cursor);
       setSessionIdOnJob(holder);
       return holder;
     } catch (InvalidJobException e) {
       // delete
       String jobId = cursor.getString(DbOpenHelper.ID_COLUMN.columnIndex);
       if (jobId == null) {
         JqLog.e("cannot find job id on a retriewed job");
       } else {
         delete(jobId);
       }
     } finally {
       cursor.close();
     }
   }
 }
 private boolean insertWithTags(JobHolder jobHolder) {
   final SQLiteStatement stmt = sqlHelper.getInsertStatement();
   final SQLiteStatement tagsStmt = sqlHelper.getInsertTagsStatement();
   db.beginTransaction();
   try {
     stmt.clearBindings();
     bindValues(stmt, jobHolder);
     boolean insertResult = stmt.executeInsert() != -1;
     if (!insertResult) {
       return false;
     }
     for (String tag : jobHolder.getTags()) {
       tagsStmt.clearBindings();
       bindTag(tagsStmt, jobHolder.getId(), tag);
       tagsStmt.executeInsert();
     }
     db.setTransactionSuccessful();
     return true;
   } catch (Throwable t) {
     JqLog.e(t, "error while inserting job with tags");
     return false;
   } finally {
     db.endTransaction();
   }
 }
 private Job safeDeserialize(byte[] bytes) {
   try {
     return jobSerializer.deserialize(bytes);
   } catch (Throwable t) {
     JqLog.e(t, "error while deserializing job");
   }
   return null;
 }
 /** {@inheritDoc} */
 @Override
 public boolean insertOrReplace(@NonNull JobHolder jobHolder) {
   if (jobHolder.getInsertionOrder() == null) {
     return insert(jobHolder);
   }
   persistJobToDisk(jobHolder);
   jobHolder.setRunningSessionId(JobManager.NOT_RUNNING_SESSION_ID);
   SQLiteStatement stmt = sqlHelper.getInsertOrReplaceStatement();
   stmt.clearBindings();
   bindValues(stmt, jobHolder);
   boolean result = stmt.executeInsert() != -1;
   JqLog.d("reinsert job result %s", result);
   return result;
 }
 /** {@inheritDoc} */
 @Override
 public JobHolder findJobById(@NonNull String id) {
   Cursor cursor = db.rawQuery(sqlHelper.FIND_BY_ID_QUERY, new String[] {id});
   try {
     if (!cursor.moveToFirst()) {
       return null;
     }
     return createJobHolderFromCursor(cursor);
   } catch (InvalidJobException e) {
     JqLog.e(e, "invalid job on findJobById");
     return null;
   } finally {
     cursor.close();
   }
 }
  @NonNull
  @Override
  public Set<JobHolder> findJobs(@NonNull Constraint constraint) {
    final Where where = createWhere(constraint);
    String selectQuery = where.findJobs(sqlHelper);
    Cursor cursor = db.rawQuery(selectQuery, where.args);
    Set<JobHolder> jobs = new HashSet<>();
    try {
      while (cursor.moveToNext()) {
        jobs.add(createJobHolderFromCursor(cursor));
      }
    } catch (InvalidJobException e) {
      JqLog.e(e, "invalid job found by tags.");
    } finally {
      cursor.close();
    }

    return jobs;
  }