Repository: xbmc/xbmc
File: xbmc/video/VideoDatabase.cpp (C++)

Code before:
  const int idFile{AddFile(fileAndPath)};
  if (idFile < 0)
    return false;

  const int oldIdFile{GetFileIdByMovie(idMovie)};
  if (oldIdFile < 0)
    return false;

  try
  {
    assert(m_pDB->in_transaction());
    std::string sql = PrepareSQL("UPDATE movie SET idFile=%i WHERE idFile=%i AND idMovie=%i",
                                 idFile, oldIdFile, idMovie);
    m_pDS->exec(sql);

    sql = PrepareSQL(
        "UPDATE videoversion SET idFile=%i WHERE idFile=%i AND media_type='movie' AND idMedia=%i",
        idFile, oldIdFile, idMovie);
    m_pDS->exec(sql);

    sql = PrepareSQL("UPDATE art SET media_id=%i WHERE media_id=%i AND media_type='videoversion'",
                     idFile, oldIdFile);
    m_pDS->exec(sql);

    if (GetSingleValueInt(PrepareSQL("SELECT idFile FROM streamdetails WHERE idFile = %i", idFile),
                          m_pDS) == 0)
    {
      sql = PrepareSQL("UPDATE streamdetails SET idFile=%i WHERE idFile=%i", idFile, oldIdFile);
      m_pDS->exec(sql);
    }
    DeleteFile(oldIdFile);

    return true;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, idFile);
  }
  return false;
}

void CVideoDatabase::DeleteFile(int idFile)
{
  // First check not multiple references to file (eg. episodes)
  std::string sql{PrepareSQL("SELECT idFile FROM movie WHERE idFile = %i UNION SELECT idFile FROM "
                             "episode WHERE idFile = %i UNION SELECT idFile FROM "
                             "videoversion WHERE idFile = %i",
                             idFile, idFile, idFile)};
  m_pDS->query(sql);
  if (m_pDS->eof())
  {

Review comment (refactor):
In this case there can't be a record with idFile == 0 in the table so nothing bad can happen but that's a dangerous way to test record existence.
"SELECT 1 FROM ..." would be guaranteed to work regardless of field types or values.

That said, GetSingleValueInt is not well suited to this use case imo and a classic DS->query followed by if (eof) is clearer, or a new Exist() helper would be better. A couple other spots in this commit use the same pattern. There may be other existing places as well.

Taking a step back, maybe the call to SetFile should happen before the stream details update of SaveFilteState. That way, existing streamdetails can be updated unconditionnally.

Code after:
  {
    std::string sql = PrepareSQL("UPDATE movie SET idFile=%i WHERE idFile=%i AND idMovie=%i",
                                 idFile, oldIdFile, idMovie);
    m_pDS->exec(sql);

    sql = PrepareSQL(
        "UPDATE videoversion SET idFile=%i WHERE idFile=%i AND media_type='movie' AND idMedia=%i",
        idFile, oldIdFile, idMovie);
    m_pDS->exec(sql);

    sql = PrepareSQL("UPDATE art SET media_id=%i WHERE media_id=%i AND media_type='videoversion'",
                     idFile, oldIdFile);
    m_pDS->exec(sql);

    sql = PrepareSQL("UPDATE streamdetails SET idFile=%i WHERE idFile=%i AND NOT EXISTS (SELECT 1 "
                     "FROM streamdetails WHERE idFile=%i)",
                     idFile, oldIdFile, idFile);
    m_pDS->exec(sql);

    return DeleteFile(oldIdFile);
  }
  catch (...)
  {
    CLog::LogF(LOGERROR, " idFile {}, fileAndPath {}, idMovie {}, oldIdFile {} - failed", idFile,
               fileAndPath, idMovie, oldIdFile);
  }
  return false;
}

bool CVideoDatabase::DeleteFile(int idFile)
{
  try
  {
    // First check no other references to file (eg. other episodes)
    std::string sql{PrepareSQL("SELECT idFile FROM movie WHERE idFile = %i "
                               "UNION SELECT idFile FROM episode WHERE idFile = %i "
                               "UNION SELECT idFile FROM videoversion WHERE idFile = %i",
                               idFile, idFile, idFile)};
    m_pDS->query(sql);
    if (m_pDS->eof())
    {
      // Get idPath
      sql = PrepareSQL("SELECT path.idPath, path.strPath FROM path "
                       "JOIN files ON path.idPath = files.idPath "
                       "WHERE idFile = %i",
                       idFile);
      m_pDS->query(sql);
      int idPath{-1};
      std::string strPath;
      if (!m_pDS->eof())
      {