/* * Utility routine for updates. * Returns: false on failure * true on success */ bool UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd, int nr_afr) { int num_rows; if (!sql_query(mdb, cmd)) { m_msg(file, line, &mdb->errmsg, _("update %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_ERROR, 0, "%s", mdb->errmsg); if (verbose) { j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return false; } if (nr_afr > 0) { num_rows = sql_affected_rows(mdb); if (num_rows < nr_afr) { char ed1[30]; m_msg(file, line, &mdb->errmsg, _("Update failed: affected_rows=%s for %s\n"), edit_uint64(num_rows, ed1), cmd); if (verbose) { // j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return false; } } mdb->changes++; return true; }
bool db_list_sql_query(JCR *jcr, B_DB *mdb, const char *query, OUTPUT_FORMATTER *sendit, e_list_type type, const char *description, bool verbose) { bool retval = false; db_lock(mdb); if (!sql_query(mdb, query, QF_STORE_RESULT)) { Mmsg(mdb->errmsg, _("Query failed: %s\n"), sql_strerror(mdb)); if (verbose) { sendit->decoration(mdb->errmsg); } goto bail_out; } sendit->array_start(description); list_result(jcr, mdb, sendit, type); sendit->array_end(description); sql_free_result(mdb); retval = true; bail_out: db_unlock(mdb); return retval; }
/* * Utility routine to do inserts * Returns: false on failure * true on success */ bool InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) { int num_rows; if (!sql_query(mdb, cmd)) { m_msg(file, line, &mdb->errmsg, _("insert %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_FATAL, 0, "%s", mdb->errmsg); if (verbose) { j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return false; } num_rows = sql_affected_rows(mdb); if (num_rows != 1) { char ed1[30]; m_msg(file, line, &mdb->errmsg, _("Insertion problem: affected_rows=%s\n"), edit_uint64(num_rows, ed1)); if (verbose) { j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return false; } mdb->changes++; return true; }
/* * Get record max. Query is already in mdb->cmd * No locking done * * Returns: -1 on failure * count on success */ int get_sql_record_max(JCR *jcr, B_DB *mdb) { SQL_ROW row; int retval = 0; if (QUERY_DB(jcr, mdb, mdb->cmd)) { if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); retval = -1; } else { retval = str_to_int64(row[0]); } sql_free_result(mdb); } else { Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); retval = -1; } return retval; }
/* * Delete Pool record, must also delete all associated * Media records. * * Returns: false on error * true on success * PoolId = number of Pools deleted (should be 1) * NumVols = number of Media records deleted */ bool db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) { bool retval = false; SQL_ROW row; int num_rows; char esc[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name)); Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc); Dmsg1(10, "selectpool: %s\n", mdb->cmd); pr->PoolId = pr->NumVols = 0; if (QUERY_DB(jcr, mdb, mdb->cmd)) { num_rows = sql_num_rows(mdb); if (num_rows == 0) { Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name); sql_free_result(mdb); goto bail_out; } else if (num_rows != 1) { Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows); sql_free_result(mdb); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb)); goto bail_out; } pr->PoolId = str_to_int64(row[0]); sql_free_result(mdb); } /* Delete Media owned by this pool */ Mmsg(mdb->cmd, "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId); pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd); Dmsg1(200, "Deleted %d Media records\n", pr->NumVols); /* Delete Pool */ Mmsg(mdb->cmd, "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId); pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd); Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId); retval = true; bail_out: db_unlock(mdb); return retval; }
/* * Utility routine for deletes * * Returns: -1 on error * n number of rows affected */ int DeleteDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) { if (!sql_query(mdb, cmd)) { m_msg(file, line, &mdb->errmsg, _("delete %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_ERROR, 0, "%s", mdb->errmsg); if (verbose) { j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return -1; } mdb->changes++; return sql_affected_rows(mdb); }
/* * Utility routine for queries. The database MUST be locked before calling here. * Returns: false on failure * true on success */ bool QueryDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) { sql_free_result(mdb); if (!sql_query(mdb, cmd, QF_STORE_RESULT)) { m_msg(file, line, &mdb->errmsg, _("query %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_FATAL, 0, "%s", mdb->errmsg); if (verbose) { j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return false; } return true; }
/* * Find the most recent successful real end time for a job given. * * RealEndTime is returned in etime * Job name is returned in job (MAX_NAME_LENGTH) * * Returns: false on failure * true on success, jr is unchanged, but etime and job are set */ bool BDB::bdb_find_last_job_end_time(JCR *jcr, JOB_DBR *jr, POOLMEM **etime, char *job) { SQL_ROW row; char ed1[50], ed2[50]; char esc_name[MAX_ESCAPE_NAME_LENGTH]; bdb_lock(); bdb_escape_string(jcr, esc_name, jr->Name, strlen(jr->Name)); pm_strcpy(etime, "0000-00-00 00:00:00"); /* default */ job[0] = 0; Mmsg(cmd, "SELECT RealEndTime, Job FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%s AND FileSetId=%s " "ORDER BY RealEndTime DESC LIMIT 1", jr->JobType, L_FULL, L_DIFFERENTIAL, L_INCREMENTAL, esc_name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); if (!QueryDB(jcr, cmd)) { Mmsg2(&errmsg, _("Query error for end time request: ERR=%s\nCMD=%s\n"), sql_strerror(), cmd); goto bail_out; } if ((row = sql_fetch_row()) == NULL) { sql_free_result(); Mmsg(errmsg, _("No prior backup Job record found.\n")); goto bail_out; } Dmsg1(100, "Got end time: %s\n", row[0]); pm_strcpy(etime, row[0]); bstrncpy(job, row[1], MAX_NAME_LENGTH); sql_free_result(); bdb_unlock(); return true; bail_out: bdb_unlock(); return false; }
/* * Find the last job start time for the specified JobLevel * * StartTime is returned in stime * Job name is returned in job (MAX_NAME_LENGTH) * * Returns: false on failure * true on success, jr is unchanged, but stime and job are set */ bool db_find_last_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime, char *job, int JobLevel) { bool retval = false; SQL_ROW row; char ed1[50], ed2[50]; char esc_name[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc_name, jr->Name, strlen(jr->Name)); pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */ job[0] = 0; Mmsg(mdb->cmd, "SELECT StartTime, Job FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, JobLevel, esc_name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); Mmsg(mdb->errmsg, _("No prior Full backup Job record found.\n")); goto bail_out; } Dmsg1(100, "Got start time: %s\n", row[0]); pm_strcpy(stime, row[0]); bstrncpy(job, row[1], MAX_NAME_LENGTH); sql_free_result(mdb); retval = true; bail_out: db_unlock(mdb); return retval; }
/* * Find job start time if JobId specified, otherwise * find last Job start time Incremental and Differential saves. * * StartTime is returned in stime * Job name is returned in job (MAX_NAME_LENGTH) * * Returns: 0 on failure * 1 on success, jr is unchanged, but stime and job are set */ bool db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime, char *job) { bool retval = false; SQL_ROW row; char ed1[50], ed2[50]; char esc_name[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc_name, jr->Name, strlen(jr->Name)); pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */ job[0] = 0; /* If no Id given, we must find corresponding job */ if (jr->JobId == 0) { /* Differential is since last Full backup */ Mmsg(mdb->cmd, "SELECT StartTime, Job FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, L_FULL, esc_name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); if (jr->JobLevel == L_DIFFERENTIAL) { /* SQL cmd for Differential backup already edited above */ /* Incremental is since last Full, Incremental, or Differential */ } else if (jr->JobLevel == L_INCREMENTAL) { /* * For an Incremental job, we must first ensure * that a Full backup was done (cmd edited above) * then we do a second look to find the most recent * backup */ if (!QUERY_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); Mmsg(mdb->errmsg, _("No prior Full backup Job record found.\n")); goto bail_out; } sql_free_result(mdb); /* Now edit SQL command for Incremental Job */ Mmsg(mdb->cmd, "SELECT StartTime, Job FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%s " "AND FileSetId=%s ORDER BY StartTime DESC LIMIT 1", jr->JobType, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, esc_name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); } else { Mmsg1(mdb->errmsg, _("Unknown level=%d\n"), jr->JobLevel); goto bail_out; } } else { Dmsg1(100, "Submitting: %s\n", mdb->cmd); Mmsg(mdb->cmd, "SELECT StartTime, Job FROM Job WHERE Job.JobId=%s", edit_int64(jr->JobId, ed1)); } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { pm_strcpy(stime, ""); /* set EOS */ Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg2(&mdb->errmsg, _("No Job record found: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); sql_free_result(mdb); goto bail_out; } Dmsg2(100, "Got start time: %s, job: %s\n", row[0], row[1]); pm_strcpy(stime, row[0]); bstrncpy(job, row[1], MAX_NAME_LENGTH); sql_free_result(mdb); retval = true; bail_out: db_unlock(mdb); return retval; }