]> Some of my projects - localmylist.git/commitdiff
PendingMyListUpdate for handling MyList edits (except for voting)
authorAPTX <marek321@gmail.com>
Sun, 3 Jun 2012 15:23:29 +0000 (17:23 +0200)
committerAPTX <marek321@gmail.com>
Sun, 3 Jun 2012 15:23:29 +0000 (17:23 +0200)
localmylist/database.cpp
localmylist/database.h
localmylist/mylist.cpp
localmylist/mylist.h
localmylist/requesthandler.cpp
localmylist/requesthandler.h
localmylist/share/schema/schema.sql

index a21e1e69f0d7359c58086f9a6fe2205af13515db..22a8793d00578147ee35e41bd7500564c2d4de92 100644 (file)
@@ -83,6 +83,19 @@ PendingRequest::PendingRequest()
        size = 0;
 }
 
+PendingMyListUpdate::PendingMyListUpdate()
+{
+       fid = 0;
+       myState = 0;
+       myFileState = 0;
+       setMyWatched = false;
+       setMyState = false;
+       setMyFileState = false;
+       setMyStorage = false;
+       setMySource = false;
+       setMyOther = false;
+}
+
 HostInfo::HostInfo()
 {
        id = 0;
@@ -126,6 +139,11 @@ struct DatabaseInternal
        QSqlQuery getRequestBatchQuery;
        QSqlQuery clearRequestQuery;
 
+       QSqlQuery addPendingMyListUpdateQuery;
+       QSqlQuery getPendingMyListUpdateQuery;
+       QSqlQuery getPendingMyListUpdateBatchQuery;
+       QSqlQuery clearPendingMyListUpdateQuery;
+
        QThread *thread;
 };
 
@@ -656,6 +674,98 @@ bool Database::clearRequest(const PendingRequest &request)
        return ret;
 }
 
+bool Database::addPendingMyListUpdate(const PendingMyListUpdate &request)
+{
+       d->addPendingMyListUpdateQuery.bindValue(":fid", request.fid);
+       d->addPendingMyListUpdateQuery.bindValue(":setMyWatched", request.setMyWatched);
+       d->addPendingMyListUpdateQuery.bindValue(":myWatched", request.myWatched);
+       d->addPendingMyListUpdateQuery.bindValue(":setMyState", request.setMyState);
+       d->addPendingMyListUpdateQuery.bindValue(":myState", request.myState);
+       d->addPendingMyListUpdateQuery.bindValue(":setMyFileState", request.setMyFileState);
+       d->addPendingMyListUpdateQuery.bindValue(":myFileState", request.myFileState);
+       d->addPendingMyListUpdateQuery.bindValue(":setMyStorage", request.setMyStorage);
+       d->addPendingMyListUpdateQuery.bindValue(":myStorage", request.myStorage);
+       d->addPendingMyListUpdateQuery.bindValue(":setMySource", request.setMySource);
+       d->addPendingMyListUpdateQuery.bindValue(":mySource", request.mySource);
+       d->addPendingMyListUpdateQuery.bindValue(":setMyOther", request.setMyOther);
+       d->addPendingMyListUpdateQuery.bindValue(":myOther", request.myOther);
+
+       return exec(d->addPendingMyListUpdateQuery);
+}
+
+PendingMyListUpdate Database::getPendingMyListUpdate(qint64 updateId)
+{
+       d->getPendingMyListUpdateQuery.bindValue(":updateId", updateId);
+
+       PendingMyListUpdate request;
+
+       if (!exec(d->getPendingMyListUpdateQuery))
+               return request;
+
+       if (d->getPendingMyListUpdateQuery.next())
+       {
+               request.updateId = d->getPendingMyListUpdateQuery.value(0).toLongLong();
+               request.fid = d->getPendingMyListUpdateQuery.value(1).toInt();
+               request.setMyWatched = d->getPendingMyListUpdateQuery.value(2).toBool();
+               request.myWatched = d->getPendingMyListUpdateQuery.value(3).toDateTime();
+               request.setMyState = d->getPendingMyListUpdateQuery.value(4).toBool();
+               request.myState = d->getPendingMyListUpdateQuery.value(5).toInt();
+               request.setMyFileState = d->getPendingMyListUpdateQuery.value(6).toBool();
+               request.myFileState = d->getPendingMyListUpdateQuery.value(7).toInt();
+               request.setMyStorage = d->getPendingMyListUpdateQuery.value(8).toBool();
+               request.myStorage = d->getPendingMyListUpdateQuery.value(9).toString();
+               request.setMySource = d->getPendingMyListUpdateQuery.value(10).toBool();
+               request.mySource = d->getPendingMyListUpdateQuery.value(11).toString();
+               request.setMyOther = d->getPendingMyListUpdateQuery.value(12).toBool();
+               request.myOther = d->getPendingMyListUpdateQuery.value(13).toString();
+               request.added = d->getPendingMyListUpdateQuery.value(14).toDateTime();
+               request.started = d->getPendingMyListUpdateQuery.value(15).toDateTime();
+       }
+       return request;
+}
+
+QList<PendingMyListUpdate> Database::getPendingMyListUpdateBatch(int limit)
+{
+       d->getPendingMyListUpdateBatchQuery.bindValue(":limit", limit);
+
+       QList<PendingMyListUpdate> ret;
+
+       if (!exec(d->getPendingMyListUpdateBatchQuery))
+               return ret;
+
+       while (d->getPendingMyListUpdateBatchQuery.next())
+       {
+               PendingMyListUpdate request;
+               request.updateId = d->getPendingMyListUpdateBatchQuery.value(0).toLongLong();
+               request.fid = d->getPendingMyListUpdateBatchQuery.value(1).toInt();
+               request.setMyWatched = d->getPendingMyListUpdateBatchQuery.value(2).toBool();
+               request.myWatched = d->getPendingMyListUpdateBatchQuery.value(3).toDateTime();
+               request.setMyState = d->getPendingMyListUpdateBatchQuery.value(4).toBool();
+               request.myState = d->getPendingMyListUpdateBatchQuery.value(5).toInt();
+               request.setMyFileState = d->getPendingMyListUpdateBatchQuery.value(6).toBool();
+               request.myFileState = d->getPendingMyListUpdateBatchQuery.value(7).toInt();
+               request.setMyStorage = d->getPendingMyListUpdateBatchQuery.value(8).toBool();
+               request.myStorage = d->getPendingMyListUpdateBatchQuery.value(9).toString();
+               request.setMySource = d->getPendingMyListUpdateBatchQuery.value(10).toBool();
+               request.mySource = d->getPendingMyListUpdateBatchQuery.value(11).toString();
+               request.setMyOther = d->getPendingMyListUpdateBatchQuery.value(12).toBool();
+               request.myOther = d->getPendingMyListUpdateBatchQuery.value(13).toString();
+               request.added = d->getPendingMyListUpdateBatchQuery.value(14).toDateTime();
+               request.started = d->getPendingMyListUpdateBatchQuery.value(15).toDateTime();
+               ret << request;
+       }
+
+       d->getPendingMyListUpdateBatchQuery.finish();
+
+       return ret;
+}
+
+bool Database::clearPendingMyListUpdate(const PendingMyListUpdate &request)
+{
+       d->clearPendingMyListUpdateQuery.bindValue(":update_id", request.updateId);
+       return exec(d->clearPendingMyListUpdateQuery);
+}
+
 bool Database::truncateTitleData()
 {
        return exec("TRUNCATE TABLE anime_title");
@@ -856,7 +966,32 @@ void Database::prepareQueries()
        d->clearRequestQuery = QSqlQuery(d->db);
        d->clearRequestQuery.prepare("DELETE FROM pending_request WHERE aid = :aid AND eid = :eid AND fid = :fid AND ed2k = :ed2k AND size = :size");
 
+       d->addPendingMyListUpdateQuery = QSqlQuery(d->db);
+       d->addPendingMyListUpdateQuery.prepare("INSERT INTO pending_mylist_update VALUES(DEFAULT, :fid, :setMyWatched, :myWatched, "
+                                                                                  ":setMyState, :myState, :setMyFileState, :myFileState, :setMyStorage, :myStorage, "
+                                                                                  ":setMySource, :mySource, :setMyOther, :myOther, DEFAULT, DEFAULT, DEFAULT)");
+
+       d->getPendingMyListUpdateBatchQuery = QSqlQuery(d->db);
+       d->getPendingMyListUpdateBatchQuery.prepare("UPDATE pending_mylist_update SET started = NOW() "
+                                                                                               "WHERE update_id IN (SELECT update_id FROM pending_mylist_update "
+                                                                                               "       WHERE started IS NULL "
+                                                                                               "       ORDER BY added ASC "
+                                                                                               "       LIMIT :limit) "
+                                                                                               "RETURNING update_id, fid, set_my_watched, my_watched, set_my_state, "
+                                                                                               "my_state, set_my_file_state, my_file_state, set_my_storage, my_storage, "
+                                                                                               "set_my_source, my_source, set_my_other, my_other, added, started");
+
+       d->getPendingMyListUpdateQuery = QSqlQuery(d->db);
+       d->getPendingMyListUpdateQuery.prepare("SELECT update_id, fid, set_my_watched, my_watched, set_my_state, my_state, "
+                                                                                  "set_my_file_state, my_file_state, set_my_storage, my_storage, set_my_source, "
+                                                                                  "my_source, set_my_other, my_other, added, started, finished "
+                                                                                  "FROM pending_mylist_update WHERE update_id = :updateId");
+
+       d->clearPendingMyListUpdateQuery = QSqlQuery(d->db);
+       d->clearPendingMyListUpdateQuery.prepare("UPDATE pending_mylist_update SET finished = NOW() WHERE update_id = :updateId");
+
        d->db.driver()->subscribeToNotification("new_pending_request");
+       d->db.driver()->subscribeToNotification("new_pending_mylist_update");
 }
 
 bool Database::exec(QSqlQuery &query)
@@ -910,6 +1045,10 @@ void Database::handleNotification(const QString &notification)
        {
                emit newPendingRequest();
        }
+       else if (notification == "new_pending_mylist_update")
+       {
+               emit newPendingMyListUpdate();
+       }
 }
 
 } // namespace LocalMyList
index 015d81f8d3f28793045bff56523b4e43c28adac4..99d8dcf2854448c2d90e947b05a0cfafc08f2206 100644 (file)
@@ -147,6 +147,30 @@ struct LOCALMYLISTSHARED_EXPORT PendingRequest
        PendingRequest();
 };
 
+struct LOCALMYLISTSHARED_EXPORT PendingMyListUpdate
+{
+       qint64 updateId;
+       int fid;
+       bool setMyWatched;
+       QDateTime myWatched;
+       bool setMyState;
+       int myState;
+       bool setMyFileState;
+       int myFileState;
+       bool setMyStorage;
+       QString myStorage;
+       bool setMySource;
+       QString mySource;
+       bool setMyOther;
+       QString myOther;
+
+       QDateTime added;
+       QDateTime started;
+       QDateTime finished;
+
+       PendingMyListUpdate();
+};
+
 struct LOCALMYLISTSHARED_EXPORT HostInfo
 {
        int id;
@@ -212,6 +236,11 @@ public:
        QList<PendingRequest> getRequestBatch(int limit = 10);
        bool clearRequest(const PendingRequest &request);
 
+       bool addPendingMyListUpdate(const PendingMyListUpdate &request);
+       PendingMyListUpdate getPendingMyListUpdate(qint64 updateId);
+       QList<PendingMyListUpdate> getPendingMyListUpdateBatch(int limit = 10);
+       bool clearPendingMyListUpdate(const PendingMyListUpdate &request);
+
        bool truncateTitleData();
        bool truncateMyListData();
        bool truncateDatabase();
@@ -229,6 +258,7 @@ signals:
        void disconnected();
 
        void newPendingRequest();
+       void newPendingMyListUpdate();
 
 private slots:
        void handleNotification(const QString &notification);
index c54c391f96ab2ad87c6aa86e2b68eadb6542fda8..17bedf5ba3712ebad45040a51f1645bb27b7849f 100644 (file)
@@ -71,9 +71,21 @@ Settings *MyList::settings() const
        return m_settings;
 }
 
-
 // -------
 
+void MyList::markWatched(int fid, QDateTime when)
+{
+       if (!fid)
+               return;
+
+       PendingMyListUpdate request;
+       request.fid = fid;
+       request.setMyWatched = true;
+       request.myWatched = when;
+       db->addPendingMyListUpdate(request);
+}
+
+
 void MyList::setupUdpClient()
 {
        using namespace ::AniDBUdpClient;
@@ -93,6 +105,7 @@ void MyList::setupRequestHandler()
 
        m_requestHandler = new RequestHandler(db, this);
        connect(db, SIGNAL(newPendingRequest()), m_requestHandler, SLOT(handleRequests()));
+       connect(db, SIGNAL(newPendingMyListUpdate()), m_requestHandler, SLOT(handleMyListUpdates()));
 }
 
 void MyList::loadLocalSettings()
index b426a7bf062de2f0809d3cdaddc0758013777c5c..3cb32b62784922cf8cb0be0bc83e0c49d2bde1bf 100644 (file)
@@ -9,6 +9,7 @@
 #include <QSet>
 #include <QDir>
 #include <QFileInfo>
+#include <QDateTime>
 
 namespace LocalMyList {
 
@@ -35,6 +36,7 @@ public:
 public slots:
        void setHostName(QString name);
 
+       void markWatched(int fid, QDateTime when = QDateTime::currentDateTime());
 
        AbstractTask *addFile(const QFileInfo &file);
        AbstractTask *addDirectory(const QDir &directory);
index 394447870034fa660039f3b38f0262d56df0b365..6adb7119b8774a0f7f270cfef6d0902bd27f5fe1 100644 (file)
@@ -19,6 +19,7 @@ RequestHandler::RequestHandler(Database *db, QObject *parent) :
 {
        this->db = db;
        connect(this, SIGNAL(batchFinished()), this, SLOT(handleRequests()), Qt::QueuedConnection);
+       connect(this, SIGNAL(myListUpdateBatchFinished()), this, SLOT(handleMyListUpdates()), Qt::QueuedConnection);
 }
 
 void RequestHandler::handleRequests()
@@ -110,6 +111,48 @@ void RequestHandler::handleRequests()
        emit batchFinished();
 }
 
+void RequestHandler::handleMyListUpdates()
+{
+       using namespace ::AniDBUdpClient;
+
+       qDebug() << "handleMyListUpdates";
+
+       db->transaction();
+       QList<PendingMyListUpdate> requests = db->getPendingMyListUpdateBatch();
+
+       qDebug() << "Got" << requests.count() << "requests";
+
+       foreach (const PendingMyListUpdate &request, requests)
+       {
+               MyListAddCommand cmd(request.fid, true);
+
+               if (request.setMyWatched)
+               {
+                       if (request.myWatched.isNull())
+                       {
+                               cmd.setViewed(false);
+                       }
+                       else
+                       {
+                               cmd.setViewed(true);
+                               cmd.setViewDate(request.myWatched);
+                       }
+               }
+               if (request.setMyState)
+                       cmd.setState(State(request.myState));
+               if (request.setMyStorage)
+                       cmd.setStorage(request.myStorage);
+               if (request.setMySource)
+                       cmd.setSource(request.mySource);
+               if (request.setMyOther)
+                       cmd.setOther(request.myOther);
+
+               MyListAddReply *reply = Client::instance()->send(cmd);
+               connect(reply, SIGNAL(replyReady(bool)), this, SLOT(myListEditReplyRecieved(bool)));
+               myListUpdateIdMap.insert(reply, request.updateId);
+       }
+}
+
 void RequestHandler::animeRequestComplete(bool success)
 {
        using namespace ::AniDBUdpClient;
@@ -420,8 +463,60 @@ void RequestHandler::myListAddReplyRecieved(bool success)
        ed2kRequest.ed2k = reply->command().ed2k();
        ed2kRequest.size = reply->command().size();
        db->clearRequest(ed2kRequest);
+}
 
+void RequestHandler::myListEditReplyRecieved(bool success)
+{
+       using namespace ::AniDBUdpClient;
+
+       MyListAddReply *reply = qobject_cast<MyListAddReply *>(sender());
 
+       Q_ASSERT(reply);
+       Q_ASSERT(myListUpdateIdMap.contains(reply));
+       reply->deleteLater();
+
+       qint64 id = myListUpdateIdMap.take(reply);
+
+       if (!success)
+               return;
+
+       db->transaction();
+       File file = db->getFile(reply->command().fid());
+
+       if (!file.fid)
+       {
+               qWarning("Updated file not in DB");
+               return;
+       }
+
+       PendingMyListUpdate request = db->getPendingMyListUpdate(id);
+
+       if (!request.updateId)
+       {
+               qWarning("PendingMyListUpdate not in DB");
+               return;
+       }
+
+       if (request.setMyWatched)
+               file.myWatched = request.myWatched;
+       if (request.setMyState)
+               file.myState = request.myState;
+       if (request.setMyFileState)
+               file.myFileState = request.myFileState;
+       if (request.setMySource)
+               file.mySource = request.mySource.isNull() ? QString("") : request.mySource;
+       if (request.setMyStorage)
+               file.myStorage = request.myStorage.isNull() ? QString("") : request.myStorage;
+       if (request.setMyOther)
+               file.myOther = request.myOther.isNull() ? QString("") : request.myOther;
+
+       file.myUpdate = QDateTime::currentDateTime();
+
+       db->setFile(file);
+
+       qDebug() << "Clearing update_id" << id;
+       db->clearPendingMyListUpdate(request);
+       db->commit();
 }
 
 } // namespace LocalMyList
index 994fa40224f599b2ec04574c6f7f6dcf48f69b30..8f2222f1d374965d336909a20e8350f929773374 100644 (file)
@@ -25,20 +25,24 @@ public:
 
 signals:
        void batchFinished();
+       void myListUpdateBatchFinished();
 
 public slots:
        void handleRequests();
+       void handleMyListUpdates();
 
        void animeRequestComplete(bool success);
        void episodeRequestComplete(bool success);
        void fileRequestComplete(bool success);
        void voteRequestComplete(bool);
        void myListAddReplyRecieved(bool success);
+       void myListEditReplyRecieved(bool success);
 
 private:
        Database *db;
 
        QMap< ::AniDBUdpClient::VoteReply *, int> idMap;
+       QMap< ::AniDBUdpClient::MyListAddReply *, qint64> myListUpdateIdMap;
 };
 
 } // namespace LocalMyList
index b4a6ae89803ee9d4f50f5cc732446101bc8c3c9d..8e2af8ec79f45488ad0a788c6d6978f447a434ec 100644 (file)
@@ -18,9 +18,9 @@ CREATE TABLE anime (
     my_vote numeric(4,2),
     my_vote_date timestamp without time zone,
     my_temp_vote numeric(4,2),
-    my_temp_vote_date timestamp without time zone
+    my_temp_vote_date timestamp without time zone,
+       CONSTRAINT aid_pk PRIMARY KEY (aid)
 );
-ALTER TABLE ONLY anime ADD CONSTRAINT aid_pk PRIMARY KEY (aid);
 CREATE INDEX rating_idx ON anime USING btree (rating);
 CREATE INDEX temp_rating_idx ON anime USING btree (temp_rating);
 CREATE INDEX my_vote_idx ON anime USING btree (my_vote);
@@ -30,9 +30,9 @@ CREATE TABLE anime_title (
     aid integer NOT NULL,
     type integer DEFAULT 1,
     language character(8) DEFAULT ''::bpchar,
-    title character varying(500) NOT NULL
+    title character varying(500) NOT NULL,
+       CONSTRAINT unique_title UNIQUE (aid, type, language, title)
 );
-ALTER TABLE ONLY anime_title ADD CONSTRAINT unique_title UNIQUE (aid, type, language, title);
 CREATE INDEX aid_idx ON anime_title USING btree (aid);
 CREATE INDEX title_idx ON anime_title USING gin (to_tsvector('simple'::regconfig, (title)::text));
 CREATE INDEX language_idx ON anime_title USING hash (language);
@@ -57,9 +57,9 @@ CREATE TABLE episode (
     rating numeric(4,2),
     votes integer,
     my_vote numeric(4,2),
-    my_vote_date timestamp without time zone
+    my_vote_date timestamp without time zone,
+       CONSTRAINT eid_pk PRIMARY KEY (eid)
 );
-ALTER TABLE ONLY episode ADD CONSTRAINT eid_pk PRIMARY KEY (eid);
 CREATE INDEX episode_aid_fk ON episode USING btree (aid);
 
 CREATE TABLE file (
@@ -94,9 +94,9 @@ CREATE TABLE file (
     my_file_state integer,
     my_storage text,
     my_source text,
-    my_other text
+    my_other text,
+       CONSTRAINT fid_pk PRIMARY KEY (fid)
 );
-ALTER TABLE ONLY file ADD CONSTRAINT fid_pk PRIMARY KEY (fid);
 CREATE INDEX file_aid_fk ON file USING btree (aid);
 CREATE INDEX file_eid_fk ON file USING btree (eid);
 
@@ -104,9 +104,9 @@ CREATE TABLE file_episode_rel (
     fid integer NOT NULL,
     eid integer NOT NULL,
     start_percent integer,
-    end_percent integer
+    end_percent integer,
+       CONSTRAINT fid_eid_pk PRIMARY KEY (fid, eid)
 );
-ALTER TABLE ONLY file_episode_rel ADD CONSTRAINT fid_eid_pk PRIMARY KEY (fid, eid);
 CREATE INDEX file_episode_rel_eid_fk ON file_episode_rel USING btree (eid);
 CREATE INDEX file_episode_rel_fid_fk ON file_episode_rel USING btree (fid);
 
@@ -120,22 +120,31 @@ CREATE TABLE unknown_file (
     ed2k character(32) NOT NULL,
     size bigint NOT NULL,
     host_id integer,
-    path text
+    path text,
+       CONSTRAINT unknown_files_pk PRIMARY KEY (ed2k, size)
 );
-ALTER TABLE ONLY unknown_file ADD CONSTRAINT unknown_files_pk PRIMARY KEY (ed2k, size);
 
-CREATE TABLE pending_mylist_update (
-    fid integer NOT NULL,
-    my_watched timestamp without time zone,
-    my_state integer,
-    my_file_state integer,
-    my_storage text,
-    my_source text,
-    my_other text,
-    added timestamp without time zone DEFAULT now(),
-    start timestamp without time zone
+CREATE TABLE pending_mylist_update
+(
+  update_id bigserial NOT NULL,
+  fid integer NOT NULL,
+  set_my_watched boolean NOT NULL DEFAULT false,
+  my_watched timestamp without time zone,
+  set_my_state boolean NOT NULL DEFAULT false,
+  my_state integer,
+  set_my_file_state boolean NOT NULL DEFAULT false,
+  my_file_state integer,
+  set_my_storage boolean NOT NULL DEFAULT false,
+  my_storage text,
+  set_my_source boolean NOT NULL DEFAULT false,
+  my_source text,
+  set_my_other boolean NOT NULL DEFAULT false,
+  my_other text,
+  added timestamp without time zone DEFAULT now(),
+  started timestamp without time zone,
+  finished timestamp without time zone,
+  CONSTRAINT pending_mylist_update_pk PRIMARY KEY (update_id )
 );
-ALTER TABLE ONLY pending_mylist_update ADD CONSTRAINT pending_mylist_update_pk PRIMARY KEY (fid);
 
 CREATE TABLE pending_request (
     aid integer DEFAULT 0 NOT NULL,
@@ -145,9 +154,9 @@ CREATE TABLE pending_request (
     size bigint DEFAULT 0 NOT NULL,
     priority integer DEFAULT 1 NOT NULL,
     added timestamp without time zone DEFAULT now(),
-    start timestamp without time zone
+    start timestamp without time zone,
+       CONSTRAINT pending_request_pk PRIMARY KEY (aid, eid, fid, ed2k, size)
 );
-ALTER TABLE ONLY pending_request ADD CONSTRAINT pending_request_pk PRIMARY KEY (aid, eid, fid, ed2k, size);
 CREATE INDEX pending_request_added_idx ON pending_request USING btree (added);
 CREATE INDEX pending_request_priority_idx ON pending_request USING btree (priority, added, start);
 CREATE INDEX pending_request_start_idx ON pending_request USING btree (start);
@@ -155,25 +164,24 @@ CREATE INDEX pending_request_start_idx ON pending_request USING btree (start);
 CREATE TABLE config (
     key character varying(250) NOT NULL,
     value text,
-    is_user_facing boolean DEFAULT false NOT NULL
+    is_user_facing boolean DEFAULT false NOT NULL,
+       CONSTRAINT config_pk PRIMARY KEY (key)
 );
 
-ALTER TABLE ONLY config ADD CONSTRAINT config_pk PRIMARY KEY (key);
-
 CREATE TABLE host (
     host_id serial NOT NULL,
     name character varying(100),
-    is_udp_host boolean DEFAULT false
+    is_udp_host boolean DEFAULT false,
+       CONSTRAINT host_pk PRIMARY KEY (host_id),
+       CONSTRAINT host_unique_name UNIQUE (name)
 );
-ALTER TABLE ONLY host ADD CONSTRAINT host_pk PRIMARY KEY (host_id);
-ALTER TABLE ONLY host ADD CONSTRAINT host_unique_name UNIQUE (name);
 
 CREATE TABLE log (
     log_id serial NOT NULL,
     type integer,
-    log text
+    log text,
+       CONSTRAINT log_pk PRIMARY KEY (log_id)
 );
-ALTER TABLE ONLY log ADD CONSTRAINT log_pk PRIMARY KEY (log_id);
 
 CREATE VIEW file_data AS
     SELECT f.fid, f.eid, f.aid, f.gid, f.anidb_update, f.entry_update, f.my_update, f.ed2k, f.size, f.length, f.extension, f.group_name, f.group_name_short, f.crc, f.release_date, f.version, f.censored, f.type, f.quality_id, f.quality, f.resolution, f.video_codec, f.audio_codec, f.audio_language, f.subtitle_language, f.aspect_ratio, f.my_watched, f.my_state, f.my_file_state, f.my_storage, f.my_source, f.my_other, a.title_romaji AS atitle, e.title_english AS eptitle FROM ((file f LEFT JOIN anime a ON ((f.aid = a.aid))) LEFT JOIN episode e ON ((f.eid = e.eid)));
@@ -193,3 +201,4 @@ CREATE RULE pending_request_ignore_duplicate AS ON INSERT TO pending_request WHE
 CREATE RULE unknown_file_ignore_duplicate AS ON INSERT TO unknown_file WHERE (EXISTS (SELECT 1 FROM unknown_file WHERE ((unknown_file.ed2k = new.ed2k) AND (unknown_file.size = new.size)))) DO INSTEAD NOTHING;
 COMMENT ON RULE unknown_file_ignore_duplicate ON unknown_file IS 'Adding the same file more than once can happen';
 
+CREATE RULE new_pending_mylist_update_rule AS ON INSERT TO pending_mylist_update DO NOTIFY new_pending_mylist_update;
\ No newline at end of file