Index: libs/libmythtv/dbcheck.cpp
===================================================================
--- libs/libmythtv/dbcheck.cpp	(revision 20431)
+++ libs/libmythtv/dbcheck.cpp	(working copy)
@@ -18,7 +18,7 @@
 #define MINIMUM_DBMS_VERSION 5,0,15
 
 /// This is the DB schema version expected by the running MythTV instance.
-const QString currentDatabaseVersion = "1232";
+const QString currentDatabaseVersion = "1233";
 
 static bool UpdateDBVersionNumber(const QString &newnumber);
 static bool performActualUpdate(
@@ -4458,6 +4458,18 @@
         if (!performActualUpdate(updates, "1232", dbver))  
             return false;  
     }   
+    if (dbver == "1232")
+    {
+        const char *updates[] = {
+"ALTER TABLE program"
+"    ADD COLUMN lastupdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP "
+"        ON UPDATE CURRENT_TIMESTAMP, "
+"    ADD INDEX program_lastupdate (lastupdate);",
+NULL
+};
+        if (!performActualUpdate(updates, "1233", dbver))
+            return false;
+    }
 
     return true;
 }
Index: libs/libmythtv/datadirect.h
===================================================================
--- libs/libmythtv/datadirect.h	(revision 20431)
+++ libs/libmythtv/datadirect.h	(working copy)
@@ -327,7 +327,7 @@
         uint sourceid, bool insert_channels, bool filter_new_channels);
     static bool UpdateChannelsUnsafe(
         uint sourceid, bool filter_new_channels);
-    static void DataDirectProgramUpdate(void);
+    static void DataDirectProgramUpdate(int sourceid, const QDateTime &from, const QDateTime &to);
 
     // static command, makes Labs and Schedules Direct ProgramIDs compatible.
     static void FixProgramIDs(void);
Index: libs/libmythtv/datadirect.cpp
===================================================================
--- libs/libmythtv/datadirect.cpp	(revision 20431)
+++ libs/libmythtv/datadirect.cpp	(working copy)
@@ -824,10 +824,93 @@
     return true;
 }
 
-void DataDirectProcessor::DataDirectProgramUpdate(void)
+void DataDirectProcessor::DataDirectProgramUpdate(int sourceid, const QDateTime &from, const QDateTime &to)
 {
     MSqlQuery query(MSqlQuery::DDCon());
 
+    query.prepare("DELETE program FROM program"
+                  " LEFT JOIN channel"
+                  "  ON program.chanid = channel.chanid"
+                  " LEFT JOIN dd_genre"
+                  "  ON program.programid = dd_genre.programid"
+                  "  AND program.category = dd_genre.class"
+                  "  AND dd_genre.relevance = '0'"
+                  " LEFT JOIN dd_v_program"
+                  "  ON program.chanid = dd_v_program.chanid"
+                  "  AND program.starttime = DATE_ADD(dd_v_program.starttime, INTERVAL channel.tmoffset MINUTE)"
+                  "  AND program.endtime = DATE_ADD(dd_v_program.endtime, INTERVAL channel.tmoffset MINUTE)"
+                  "  AND program.title = dd_v_program.title"
+                  "  AND program.subtitle = dd_v_program.subtitle"
+                  "  AND program.description = dd_v_program.description"
+                  "  AND program.showtype = dd_v_program.showtype"
+                  "  AND program.category_type = dd_v_program.category_type"
+                  "  AND program.airdate = dd_v_program.airdate"
+                  "  AND program.stars = dd_v_program.stars"
+                  "  AND program.stereo = dd_v_program.stereo"
+                  "  AND program.subtitled = dd_v_program.subtitled"
+                  "  AND program.subtitletypes = (dd_v_program.subtitled << 1) | dd_v_program.closecaptioned"
+                  "  AND program.videoprop = dd_v_program.hdtv"
+                  "  AND program.audioprop = (dd_v_program.dolby >> 3) | dd_v_program.stereo"
+                  "  AND program.hdtv = dd_v_program.hdtv"
+                  "  AND program.closecaptioned = dd_v_program.closecaptioned"
+                  "  AND program.partnumber = dd_v_program.partnumber"
+                  "  AND program.parttotal = dd_v_program.parttotal"
+                  "  AND program.seriesid = dd_v_program.seriesid"
+                  "  AND program.originalairdate = dd_v_program.originalairdate"
+                  "  AND program.colorcode = dd_v_program.colorcode"
+                  "  AND program.syndicatedepisodenumber = dd_v_program.syndicatedepisodenumber"
+                  "  AND program.programid = dd_v_program.programid"
+                  " WHERE"
+                  "  (channel.chanid is NULL"
+                  "   OR dd_genre.programid is NULL"
+                  "   OR dd_v_program.chanid is NULL)"
+                  "  AND program.starttime >= DATE_ADD(:FROM, INTERVAL channel.tmoffset MINUTE)"
+                  "  AND program.starttime < DATE_ADD(:TO, INTERVAL channel.tmoffset MINUTE)"
+                  "  AND channel.sourceid = :SOURCEID"
+                  "  AND program.originalairdate = dd_v_program.originalairdate"
+                  ";");
+    query.bindValue(":FROM", from);
+    query.bindValue(":TO", to);
+    query.bindValue(":SOURCEID", sourceid);
+    if (!query.exec())
+        MythDB::DBError("Deleting changed entries from program table", query);
+
+    query.prepare("DELETE dd_v_program FROM dd_v_program"
+                  " INNER JOIN channel"
+                  "  ON dd_v_program.chanid = channel.chanid"
+                  " INNER JOIN dd_genre"
+                  "  ON dd_v_program.programid = dd_genre.programid"
+                  "  AND dd_genre.relevance = '0'"
+                  " INNER JOIN program"
+                  "  ON program.chanid = dd_v_program.chanid"
+                  "  AND program.starttime = DATE_ADD(dd_v_program.starttime, INTERVAL channel.tmoffset MINUTE)"
+                  "  AND program.endtime = DATE_ADD(dd_v_program.endtime, INTERVAL channel.tmoffset MINUTE)"
+                  "  AND program.title = dd_v_program.title"
+                  "  AND program.subtitle = dd_v_program.subtitle"
+                  "  AND program.description = dd_v_program.description"
+                  "  AND program.showtype = dd_v_program.showtype"
+                  "  AND program.category = dd_genre.class"
+                  "  AND program.category_type = dd_v_program.category_type"
+                  "  AND program.airdate = dd_v_program.airdate"
+                  "  AND program.stars = dd_v_program.stars"
+                  "  AND program.stereo = dd_v_program.stereo"
+                  "  AND program.subtitled = dd_v_program.subtitled"
+                  "  AND program.subtitletypes = (dd_v_program.subtitled << 1) | dd_v_program.closecaptioned"
+                  "  AND program.videoprop = dd_v_program.hdtv"
+                  "  AND program.audioprop = (dd_v_program.dolby >> 3) | dd_v_program.stereo"
+                  "  AND program.hdtv = dd_v_program.hdtv"
+                  "  AND program.closecaptioned = dd_v_program.closecaptioned"
+                  "  AND program.partnumber = dd_v_program.partnumber"
+                  "  AND program.parttotal = dd_v_program.parttotal"
+                  "  AND program.seriesid = dd_v_program.seriesid"
+                  "  AND program.originalairdate = dd_v_program.originalairdate"
+                  "  AND program.colorcode = dd_v_program.colorcode"
+                  "  AND program.syndicatedepisodenumber = dd_v_program.syndicatedepisodenumber"
+                  "  AND program.programid = dd_v_program.programid"
+                  ";");
+    if (!query.exec())
+        MythDB::DBError("Deleting up-to-date entries from listings source data", query);
+
     //cerr << "Adding rows to main program table from view table..\n";
     if (!query.exec("INSERT IGNORE INTO program (chanid, starttime, endtime, "
                     "title, subtitle, description, "
Index: libs/libmythtv/programdata.cpp
===================================================================
--- libs/libmythtv/programdata.cpp	(revision 20431)
+++ libs/libmythtv/programdata.cpp	(working copy)
@@ -27,7 +27,7 @@
     return false;
 }
 
-void ProgramData::clearDataByChannel(int chanid, QDateTime from, QDateTime to)
+void ProgramData::clearDataByChannel(int chanid, QDateTime from, QDateTime to, bool clearprogram)
 {
     int secs;
     QDateTime newFrom, newTo;
@@ -49,13 +49,15 @@
     newFrom = from.addSecs(secs);
     newTo = to.addSecs(secs);
 
-    query.prepare("DELETE FROM program "
-                  "WHERE starttime >= :FROM AND starttime < :TO "
-                  "AND chanid = :CHANID ;");
-    query.bindValue(":FROM", newFrom);
-    query.bindValue(":TO", newTo);
-    query.bindValue(":CHANID", chanid);
-    query.exec();
+    if (clearprogram) {
+        query.prepare("DELETE FROM program "
+                      "WHERE starttime >= :FROM AND starttime < :TO "
+                      "AND chanid = :CHANID ;");
+        query.bindValue(":FROM", newFrom);
+        query.bindValue(":TO", newTo);
+        query.bindValue(":CHANID", chanid);
+        query.exec();
+    }
 
     query.prepare("DELETE FROM programrating "
                   "WHERE starttime >= :FROM AND starttime < :TO "
@@ -82,7 +84,7 @@
     query.exec();
 }
 
-void ProgramData::clearDataBySource(int sourceid, QDateTime from, QDateTime to)
+void ProgramData::clearDataBySource(int sourceid, QDateTime from, QDateTime to, bool clearprogram)
 {
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("SELECT chanid FROM channel WHERE "
@@ -97,7 +99,7 @@
         while (query.next())
         {
             int chanid = query.value(0).toInt();
-            clearDataByChannel(chanid, from, to);
+            clearDataByChannel(chanid, from, to, clearprogram);
         }
     }
 }
Index: libs/libmythtv/programdata.h
===================================================================
--- libs/libmythtv/programdata.h	(revision 20431)
+++ libs/libmythtv/programdata.h	(working copy)
@@ -104,8 +104,10 @@
                         QMap<QString, QList<ProgInfo> > *proglist);
 
     static int  fix_end_times(void);
-    static void clearDataByChannel(int chanid, QDateTime from, QDateTime to);
-    static void clearDataBySource(int sourceid, QDateTime from, QDateTime to);
+    static void clearDataByChannel(int chanid, QDateTime from, QDateTime to,
+                                   bool clearprogram = FALSE);
+    static void clearDataBySource(int sourceid, QDateTime from, QDateTime to,
+                                  bool clearprogram = FALSE);
 
   private:
     void fixProgramList(QList<ProgInfo> *fixlist);
Index: programs/mythfilldatabase/filldata.cpp
===================================================================
--- programs/mythfilldatabase/filldata.cpp	(revision 20431)
+++ programs/mythfilldatabase/filldata.cpp	(working copy)
@@ -308,7 +308,8 @@
     VERBOSE(VB_GENERAL, "Data for source cleared.");
 
     VERBOSE(VB_GENERAL, "Updating programs.");
-    DataDirectProcessor::DataDirectProgramUpdate();
+    DataDirectProcessor::DataDirectProgramUpdate(source.id, fromlocaldt,
+                                                 tolocaldt);
     VERBOSE(VB_GENERAL, "Program table update complete.");
 
     return true;
Index: programs/mythfilldatabase/main.cpp
===================================================================
--- programs/mythfilldatabase/main.cpp	(revision 20431)
+++ programs/mythfilldatabase/main.cpp	(working copy)
@@ -713,7 +713,7 @@
         query.prepare("UPDATE program SET generic = 1 WHERE "
             "((programid = '' AND subtitle = '' AND description = '') OR "
             " (programid <> '' AND category_type = 'series' AND "
-            "  program.programid LIKE '%0000'));");
+            "  program.programid LIKE '%0000') AND generic <> 1);");
 
         if (!query.exec())
             MythDB::DBError("mark generic", query);
@@ -814,7 +814,6 @@
     if (grab_data)
     {
         MSqlQuery updt(MSqlQuery::InitCon());
-        updt.exec("UPDATE program SET first = 0, last = 0;");
 
         VERBOSE(VB_GENERAL, "Marking episode first showings.");
 
@@ -828,10 +827,19 @@
             {
                 updt.prepare("UPDATE program set first = 1 "
                              "WHERE starttime = :STARTTIME "
-                             "  AND programid = :PROGRAMID;");
+                             "  AND programid = :PROGRAMID "
+                             "  AND first <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":PROGRAMID", query.value(1).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set first = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND programid = :PROGRAMID "
+                             "  AND first <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":PROGRAMID", query.value(1).toString());
+                updt.exec();
             }
         }
         int found = query.size();
@@ -848,12 +856,25 @@
                              "WHERE starttime = :STARTTIME "
                              "  AND title = :TITLE "
                              "  AND subtitle = :SUBTITLE "
-                             "  AND description = :DESCRIPTION");
+                             "  AND description = :DESCRIPTION "
+                             "  AND first <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":TITLE", query.value(1).toString());
                 updt.bindValue(":SUBTITLE", query.value(2).toString());
                 updt.bindValue(":DESCRIPTION", query.value(3).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set first = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND title = :TITLE "
+                             "  AND subtitle = :SUBTITLE "
+                             "  AND description = :DESCRIPTION "
+                             "  AND first <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":TITLE", query.value(1).toString());
+                updt.bindValue(":SUBTITLE", query.value(2).toString());
+                updt.bindValue(":DESCRIPTION", query.value(3).toString());
+                updt.exec();
             }
         }
         found += query.size();
@@ -870,10 +891,19 @@
             {
                 updt.prepare("UPDATE program set last = 1 "
                              "WHERE starttime = :STARTTIME "
-                             "  AND programid = :PROGRAMID;");
+                             "  AND programid = :PROGRAMID "
+                             "  AND last <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":PROGRAMID", query.value(1).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set last = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND programid = :PROGRAMID "
+                             "  AND last <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":PROGRAMID", query.value(1).toString());
+                updt.exec();
             }
         }
         found = query.size();
@@ -890,12 +920,25 @@
                              "WHERE starttime = :STARTTIME "
                              "  AND title = :TITLE "
                              "  AND subtitle = :SUBTITLE "
-                             "  AND description = :DESCRIPTION");
+                             "  AND description = :DESCRIPTION "
+                             "  AND last <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":TITLE", query.value(1).toString());
                 updt.bindValue(":SUBTITLE", query.value(2).toString());
                 updt.bindValue(":DESCRIPTION", query.value(3).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set last = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND title = :TITLE "
+                             "  AND subtitle = :SUBTITLE "
+                             "  AND description = :DESCRIPTION "
+                             "  AND last <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":TITLE", query.value(1).toString());
+                updt.bindValue(":SUBTITLE", query.value(2).toString());
+                updt.bindValue(":DESCRIPTION", query.value(3).toString());
+                updt.exec();
             }
         }
         found += query.size();
