From ed8e7be57a261c127be864329ef6c8ba9e98f217 Mon Sep 17 00:00:00 2001 From: "gavin%gavinsharp.com" Date: Tue, 29 Apr 2008 19:21:12 +0000 Subject: [PATCH] Bug 421180: When removing bookmarks existing keywords aren't deleted/removed, patch by Marco Bonardo , r=dietrich, a=damon git-svn-id: svn://10.0.0.236/trunk@250945 18797224-902f-48f8-a5cc-f745e15eee43 --- .../components/places/src/nsNavHistory.cpp | 39 ++++++ .../places/tests/unit/test_421180.js | 114 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 mozilla/toolkit/components/places/tests/unit/test_421180.js diff --git a/mozilla/toolkit/components/places/src/nsNavHistory.cpp b/mozilla/toolkit/components/places/src/nsNavHistory.cpp index 82fd22d52d1..d6df0e9fee6 100644 --- a/mozilla/toolkit/components/places/src/nsNavHistory.cpp +++ b/mozilla/toolkit/components/places/src/nsNavHistory.cpp @@ -928,9 +928,48 @@ nsNavHistory::CreateTriggers() NS_ENSURE_SUCCESS(rv, rv); rv = createTriggersTransaction.Commit(); + NS_ENSURE_SUCCESS(rv, rv); } + // we are creating 1 trigger on moz_bookmarks to remove unused keywords + nsCOMPtr detectRemoveKeywordsTrigger; + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT name FROM sqlite_master WHERE type = 'trigger' AND " + "name = 'moz_bookmarks_beforedelete_v1_trigger'"), + getter_AddRefs(detectRemoveKeywordsTrigger)); NS_ENSURE_SUCCESS(rv, rv); + + hasTrigger = PR_FALSE; + rv = detectRemoveKeywordsTrigger->ExecuteStep(&hasTrigger); + NS_ENSURE_SUCCESS(rv, rv); + rv = detectRemoveKeywordsTrigger->Reset(); + NS_ENSURE_SUCCESS(rv, rv); + + if (!hasTrigger) { + // Remove dangling keywords. + // We must remove old keywords that have not been deleted with bookmarks. + // See bug 421180 for details. + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "DELETE FROM moz_keywords WHERE id IN (" + "SELECT k.id FROM moz_keywords k " + "LEFT OUTER JOIN moz_bookmarks b ON b.keyword_id = k.id " + "WHERE b.id IS NULL)")); + NS_ENSURE_SUCCESS(rv, rv); + + // moz_bookmarks_beforedelete_v1_trigger + // Remove keywords if there are no more bookmarks using them. + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TRIGGER IF NOT EXISTS moz_bookmarks_beforedelete_v1_trigger " + "BEFORE DELETE ON moz_bookmarks FOR EACH ROW " + "WHEN OLD.keyword_id NOT NULL " + "BEGIN " + "DELETE FROM moz_keywords WHERE id = OLD.keyword_id AND " + " NOT EXISTS (SELECT id FROM moz_bookmarks " + "WHERE keyword_id = OLD.keyword_id AND id <> OLD.id LIMIT 1); " + "END")); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; } diff --git a/mozilla/toolkit/components/places/tests/unit/test_421180.js b/mozilla/toolkit/components/places/tests/unit/test_421180.js new file mode 100644 index 00000000000..1806e34c419 --- /dev/null +++ b/mozilla/toolkit/components/places/tests/unit/test_421180.js @@ -0,0 +1,114 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Places unit test code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +// Get bookmarks service +try { + var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); +} +catch(ex) { + do_throw("Could not get bookmarks service\n"); +} + +// Get database connection +try { + var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); + var storage = Cc["@mozilla.org/storage/service;1"]. + getService(Ci.mozIStorageService); + var database = dirSvc.get('ProfD', Ci.nsIFile); + database.append("places.sqlite"); + var mDBConn = storage.openDatabase(database); +} +catch(ex) { + do_throw("Could not get database connection\n"); +} + +// main +function run_test() { + var bookmarkedURI = uri("http://foo.bar"); + var keyword = "testkeyword"; + + // TEST 1 + // 1. add a bookmark + // 2. add a keyword to it + // 3. remove bookmark + // 4. check that keyword has gone + var bookmarkId = bmsvc.insertBookmark(bmsvc.bookmarksMenuFolder, + bookmarkedURI, + bmsvc.DEFAULT_INDEX, + "A bookmark"); + bmsvc.setKeywordForBookmark(bookmarkId, keyword); + // remove bookmark + bmsvc.removeItem(bookmarkId); + + // check that keyword has been removed + var sql = "SELECT id FROM moz_keywords WHERE keyword = ?1"; + var stmt = mDBConn.createStatement(sql); + stmt.bindUTF8StringParameter(0, keyword); + do_check_false(stmt.executeStep()); + + + // TEST 2 + // 1. add 2 bookmarks + // 2. add the same keyword to them + // 3. remove first bookmark + // 4. check that keyword is still there + var bookmarkId1 = bmsvc.insertBookmark(bmsvc.bookmarksMenuFolder, + bookmarkedURI, + bmsvc.DEFAULT_INDEX, + "A bookmark"); + bmsvc.setKeywordForBookmark(bookmarkId1, keyword); + + var bookmarkId2 = bmsvc.insertBookmark(bmsvc.toolbarFolder, + bookmarkedURI, + bmsvc.DEFAULT_INDEX, + keyword); + bmsvc.setKeywordForBookmark(bookmarkId2, keyword); + + // remove first bookmark + bmsvc.removeItem(bookmarkId1); + + // check that keyword is still there + var sql = "SELECT id FROM moz_keywords WHERE keyword = ?1"; + var stmt = mDBConn.createStatement(sql); + stmt.bindUTF8StringParameter(0, keyword); + do_check_true(stmt.executeStep()); + +}