Bug 1057782 - Use template strings for multi-line SQL statements. r=ttaubert

This commit is contained in:
Michael Pruett 2014-08-23 18:12:43 -05:00
parent 4a33fc10a0
commit d05c5d9bc9
6 changed files with 511 additions and 523 deletions

View File

@ -285,53 +285,53 @@ this.PlacesDBUtils = {
// The 'weave0' idiom exploits character ordering (0 follows /) to
// efficiently select all annos with a 'weave/' prefix.
let deleteObsoleteAnnos = DBConn.createAsyncStatement(
"DELETE FROM moz_annos " +
"WHERE anno_attribute_id IN ( " +
" SELECT id FROM moz_anno_attributes " +
" WHERE name BETWEEN 'weave/' AND 'weave0' " +
")");
`DELETE FROM moz_annos
WHERE anno_attribute_id IN (
SELECT id FROM moz_anno_attributes
WHERE name BETWEEN 'weave/' AND 'weave0'
)`);
cleanupStatements.push(deleteObsoleteAnnos);
// A.2 remove obsolete annotations from moz_items_annos.
let deleteObsoleteItemsAnnos = DBConn.createAsyncStatement(
"DELETE FROM moz_items_annos " +
"WHERE anno_attribute_id IN ( " +
" SELECT id FROM moz_anno_attributes " +
" WHERE name = 'sync/children' " +
" OR name = 'placesInternal/GUID' " +
" OR name BETWEEN 'weave/' AND 'weave0' " +
")");
`DELETE FROM moz_items_annos
WHERE anno_attribute_id IN (
SELECT id FROM moz_anno_attributes
WHERE name = 'sync/children'
OR name = 'placesInternal/GUID'
OR name BETWEEN 'weave/' AND 'weave0'
)`);
cleanupStatements.push(deleteObsoleteItemsAnnos);
// A.3 remove unused attributes.
let deleteUnusedAnnoAttributes = DBConn.createAsyncStatement(
"DELETE FROM moz_anno_attributes WHERE id IN ( " +
"SELECT id FROM moz_anno_attributes n " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_annos WHERE anno_attribute_id = n.id LIMIT 1) " +
"AND NOT EXISTS " +
"(SELECT id FROM moz_items_annos WHERE anno_attribute_id = n.id LIMIT 1) " +
")");
`DELETE FROM moz_anno_attributes WHERE id IN (
SELECT id FROM moz_anno_attributes n
WHERE NOT EXISTS
(SELECT id FROM moz_annos WHERE anno_attribute_id = n.id LIMIT 1)
AND NOT EXISTS
(SELECT id FROM moz_items_annos WHERE anno_attribute_id = n.id LIMIT 1)
)`);
cleanupStatements.push(deleteUnusedAnnoAttributes);
// MOZ_ANNOS
// B.1 remove annos with an invalid attribute
let deleteInvalidAttributeAnnos = DBConn.createAsyncStatement(
"DELETE FROM moz_annos WHERE id IN ( " +
"SELECT id FROM moz_annos a " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_anno_attributes " +
"WHERE id = a.anno_attribute_id LIMIT 1) " +
")");
`DELETE FROM moz_annos WHERE id IN (
SELECT id FROM moz_annos a
WHERE NOT EXISTS
(SELECT id FROM moz_anno_attributes
WHERE id = a.anno_attribute_id LIMIT 1)
)`);
cleanupStatements.push(deleteInvalidAttributeAnnos);
// B.2 remove orphan annos
let deleteOrphanAnnos = DBConn.createAsyncStatement(
"DELETE FROM moz_annos WHERE id IN ( " +
"SELECT id FROM moz_annos a " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_places WHERE id = a.place_id LIMIT 1) " +
")");
`DELETE FROM moz_annos WHERE id IN (
SELECT id FROM moz_annos a
WHERE NOT EXISTS
(SELECT id FROM moz_places WHERE id = a.place_id LIMIT 1)
)`);
cleanupStatements.push(deleteOrphanAnnos);
// MOZ_BOOKMARKS_ROOTS
@ -344,18 +344,18 @@ this.PlacesDBUtils = {
if (!selectPlacesRoot.executeStep()) {
// We are missing the root, try to recreate it.
let createPlacesRoot = DBConn.createAsyncStatement(
"INSERT INTO moz_bookmarks (id, type, fk, parent, position, title, "
+ "guid) "
+ "VALUES (:places_root, 2, NULL, 0, 0, :title, GENERATE_GUID())");
`INSERT INTO moz_bookmarks (id, type, fk, parent, position, title,
guid)
VALUES (:places_root, 2, NULL, 0, 0, :title, GENERATE_GUID())`);
createPlacesRoot.params["places_root"] = PlacesUtils.placesRootId;
createPlacesRoot.params["title"] = "";
cleanupStatements.push(createPlacesRoot);
// Now ensure that other roots are children of Places root.
let fixPlacesRootChildren = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET parent = :places_root WHERE id IN " +
"(SELECT folder_id FROM moz_bookmarks_roots " +
"WHERE folder_id <> :places_root)");
`UPDATE moz_bookmarks SET parent = :places_root WHERE id IN
(SELECT folder_id FROM moz_bookmarks_roots
WHERE folder_id <> :places_root)`);
fixPlacesRootChildren.params["places_root"] = PlacesUtils.placesRootId;
cleanupStatements.push(fixPlacesRootChildren);
}
@ -364,8 +364,8 @@ this.PlacesDBUtils = {
// C.2 fix roots titles
// some alpha version has wrong roots title, and this also fixes them if
// locale has changed.
let updateRootTitleSql = "UPDATE moz_bookmarks SET title = :title " +
"WHERE id = :root_id AND title <> :title";
let updateRootTitleSql = `UPDATE moz_bookmarks SET title = :title
WHERE id = :root_id AND title <> :title`;
// root
let fixPlacesRootTitle = DBConn.createAsyncStatement(updateRootTitleSql);
fixPlacesRootTitle.params["root_id"] = PlacesUtils.placesRootId;
@ -400,67 +400,67 @@ this.PlacesDBUtils = {
// D.1 remove items without a valid place
// if fk IS NULL we fix them in D.7
let deleteNoPlaceItems = DBConn.createAsyncStatement(
"DELETE FROM moz_bookmarks WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
"SELECT b.id FROM moz_bookmarks b " +
"WHERE fk NOT NULL AND b.type = :bookmark_type " +
"AND NOT EXISTS (SELECT url FROM moz_places WHERE id = b.fk LIMIT 1) " +
")");
`DELETE FROM moz_bookmarks WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT b.id FROM moz_bookmarks b
WHERE fk NOT NULL AND b.type = :bookmark_type
AND NOT EXISTS (SELECT url FROM moz_places WHERE id = b.fk LIMIT 1)
)`);
deleteNoPlaceItems.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
cleanupStatements.push(deleteNoPlaceItems);
// D.2 remove items that are not uri bookmarks from tag containers
let deleteBogusTagChildren = DBConn.createAsyncStatement(
"DELETE FROM moz_bookmarks WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
"SELECT b.id FROM moz_bookmarks b " +
"WHERE b.parent IN " +
"(SELECT id FROM moz_bookmarks WHERE parent = :tags_folder) " +
"AND b.type <> :bookmark_type " +
")");
`DELETE FROM moz_bookmarks WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT b.id FROM moz_bookmarks b
WHERE b.parent IN
(SELECT id FROM moz_bookmarks WHERE parent = :tags_folder)
AND b.type <> :bookmark_type
)`);
deleteBogusTagChildren.params["tags_folder"] = PlacesUtils.tagsFolderId;
deleteBogusTagChildren.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
cleanupStatements.push(deleteBogusTagChildren);
// D.3 remove empty tags
let deleteEmptyTags = DBConn.createAsyncStatement(
"DELETE FROM moz_bookmarks WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
"SELECT b.id FROM moz_bookmarks b " +
"WHERE b.id IN " +
"(SELECT id FROM moz_bookmarks WHERE parent = :tags_folder) " +
"AND NOT EXISTS " +
"(SELECT id from moz_bookmarks WHERE parent = b.id LIMIT 1) " +
")");
`DELETE FROM moz_bookmarks WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT b.id FROM moz_bookmarks b
WHERE b.id IN
(SELECT id FROM moz_bookmarks WHERE parent = :tags_folder)
AND NOT EXISTS
(SELECT id from moz_bookmarks WHERE parent = b.id LIMIT 1)
)`);
deleteEmptyTags.params["tags_folder"] = PlacesUtils.tagsFolderId;
cleanupStatements.push(deleteEmptyTags);
// D.4 move orphan items to unsorted folder
let fixOrphanItems = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN (" +
"SELECT b.id FROM moz_bookmarks b " +
"WHERE b.parent <> 0 " + // exclude Places root
"AND NOT EXISTS " +
"(SELECT id FROM moz_bookmarks WHERE id = b.parent LIMIT 1) " +
")");
`UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT b.id FROM moz_bookmarks b
WHERE b.parent <> 0 /* exclude Places root */
AND NOT EXISTS
(SELECT id FROM moz_bookmarks WHERE id = b.parent LIMIT 1)
)`);
fixOrphanItems.params["unsorted_folder"] = PlacesUtils.unfiledBookmarksFolderId;
cleanupStatements.push(fixOrphanItems);
// D.5 fix wrong keywords
let fixInvalidKeywords = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET keyword_id = NULL WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
"SELECT id FROM moz_bookmarks b " +
"WHERE keyword_id NOT NULL " +
"AND NOT EXISTS " +
"(SELECT id FROM moz_keywords WHERE id = b.keyword_id LIMIT 1) " +
")");
`UPDATE moz_bookmarks SET keyword_id = NULL WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT id FROM moz_bookmarks b
WHERE keyword_id NOT NULL
AND NOT EXISTS
(SELECT id FROM moz_keywords WHERE id = b.keyword_id LIMIT 1)
)`);
cleanupStatements.push(fixInvalidKeywords);
// D.6 fix wrong item types
@ -468,13 +468,13 @@ this.PlacesDBUtils = {
// If they have a valid fk convert them to bookmarks. Later in D.9 we
// will move eventual children to unsorted bookmarks.
let fixBookmarksAsFolders = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET type = :bookmark_type WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
"SELECT id FROM moz_bookmarks b " +
"WHERE type IN (:folder_type, :separator_type) " +
"AND fk NOTNULL " +
")");
`UPDATE moz_bookmarks SET type = :bookmark_type WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT id FROM moz_bookmarks b
WHERE type IN (:folder_type, :separator_type)
AND fk NOTNULL
)`);
fixBookmarksAsFolders.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
fixBookmarksAsFolders.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
fixBookmarksAsFolders.params["separator_type"] = PlacesUtils.bookmarks.TYPE_SEPARATOR;
@ -484,13 +484,13 @@ this.PlacesDBUtils = {
// Bookmarks should have an fk, if they don't have any, convert them to
// folders.
let fixFoldersAsBookmarks = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET type = :folder_type WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
"SELECT id FROM moz_bookmarks b " +
"WHERE type = :bookmark_type " +
"AND fk IS NULL " +
")");
`UPDATE moz_bookmarks SET type = :folder_type WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT id FROM moz_bookmarks b
WHERE type = :bookmark_type
AND fk IS NULL
)`);
fixFoldersAsBookmarks.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
fixFoldersAsBookmarks.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
cleanupStatements.push(fixFoldersAsBookmarks);
@ -499,15 +499,15 @@ this.PlacesDBUtils = {
// Items cannot have separators or other bookmarks
// as parent, if they have bad parent move them to unsorted bookmarks.
let fixInvalidParents = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN ( " +
"SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
") AND id IN ( " +
"SELECT id FROM moz_bookmarks b " +
"WHERE EXISTS " +
"(SELECT id FROM moz_bookmarks WHERE id = b.parent " +
"AND type IN (:bookmark_type, :separator_type) " +
"LIMIT 1) " +
")");
`UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN (
SELECT folder_id FROM moz_bookmarks_roots /* skip roots */
) AND id IN (
SELECT id FROM moz_bookmarks b
WHERE EXISTS
(SELECT id FROM moz_bookmarks WHERE id = b.parent
AND type IN (:bookmark_type, :separator_type)
LIMIT 1)
)`);
fixInvalidParents.params["unsorted_folder"] = PlacesUtils.unfiledBookmarksFolderId;
fixInvalidParents.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
fixInvalidParents.params["separator_type"] = PlacesUtils.bookmarks.TYPE_SEPARATOR;
@ -520,41 +520,41 @@ this.PlacesDBUtils = {
// triangular numbers obtained by the number of children (n).
// SUM(DISTINCT position + 1) == (n * (n + 1) / 2).
cleanupStatements.push(DBConn.createAsyncStatement(
"CREATE TEMP TABLE IF NOT EXISTS moz_bm_reindex_temp ( " +
" id INTEGER PRIMARY_KEY " +
", parent INTEGER " +
", position INTEGER " +
") "
`CREATE TEMP TABLE IF NOT EXISTS moz_bm_reindex_temp (
id INTEGER PRIMARY_KEY
, parent INTEGER
, position INTEGER
)`
));
cleanupStatements.push(DBConn.createAsyncStatement(
"INSERT INTO moz_bm_reindex_temp " +
"SELECT id, parent, 0 " +
"FROM moz_bookmarks b " +
"WHERE parent IN ( " +
"SELECT parent " +
"FROM moz_bookmarks " +
"GROUP BY parent " +
"HAVING (SUM(DISTINCT position + 1) - (count(*) * (count(*) + 1) / 2)) <> 0 " +
") " +
"ORDER BY parent ASC, position ASC, ROWID ASC "
`INSERT INTO moz_bm_reindex_temp
SELECT id, parent, 0
FROM moz_bookmarks b
WHERE parent IN (
SELECT parent
FROM moz_bookmarks
GROUP BY parent
HAVING (SUM(DISTINCT position + 1) - (count(*) * (count(*) + 1) / 2)) <> 0
)
ORDER BY parent ASC, position ASC, ROWID ASC`
));
cleanupStatements.push(DBConn.createAsyncStatement(
"CREATE INDEX IF NOT EXISTS moz_bm_reindex_temp_index " +
"ON moz_bm_reindex_temp(parent)"
`CREATE INDEX IF NOT EXISTS moz_bm_reindex_temp_index
ON moz_bm_reindex_temp(parent)`
));
cleanupStatements.push(DBConn.createAsyncStatement(
"UPDATE moz_bm_reindex_temp SET position = ( " +
"ROWID - (SELECT MIN(t.ROWID) FROM moz_bm_reindex_temp t " +
"WHERE t.parent = moz_bm_reindex_temp.parent) " +
") "
`UPDATE moz_bm_reindex_temp SET position = (
ROWID - (SELECT MIN(t.ROWID) FROM moz_bm_reindex_temp t
WHERE t.parent = moz_bm_reindex_temp.parent)
)`
));
cleanupStatements.push(DBConn.createAsyncStatement(
"CREATE TEMP TRIGGER IF NOT EXISTS moz_bm_reindex_temp_trigger " +
"BEFORE DELETE ON moz_bm_reindex_temp " +
"FOR EACH ROW " +
"BEGIN " +
"UPDATE moz_bookmarks SET position = OLD.position WHERE id = OLD.id; " +
"END "
`CREATE TEMP TRIGGER IF NOT EXISTS moz_bm_reindex_temp_trigger
BEFORE DELETE ON moz_bm_reindex_temp
FOR EACH ROW
BEGIN
UPDATE moz_bookmarks SET position = OLD.position WHERE id = OLD.id;
END`
));
cleanupStatements.push(DBConn.createAsyncStatement(
"DELETE FROM moz_bm_reindex_temp "
@ -573,9 +573,9 @@ this.PlacesDBUtils = {
// Tags were allowed to have empty names due to a UI bug. Fix them
// replacing their title with "(notitle)".
let fixEmptyNamedTags = DBConn.createAsyncStatement(
"UPDATE moz_bookmarks SET title = :empty_title " +
"WHERE length(title) = 0 AND type = :folder_type " +
"AND parent = :tags_folder"
`UPDATE moz_bookmarks SET title = :empty_title
WHERE length(title) = 0 AND type = :folder_type
AND parent = :tags_folder`
);
fixEmptyNamedTags.params["empty_title"] = "(notitle)";
fixEmptyNamedTags.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
@ -585,107 +585,107 @@ this.PlacesDBUtils = {
// MOZ_FAVICONS
// E.1 remove orphan icons
let deleteOrphanIcons = DBConn.createAsyncStatement(
"DELETE FROM moz_favicons WHERE id IN (" +
"SELECT id FROM moz_favicons f " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_places WHERE favicon_id = f.id LIMIT 1) " +
")");
`DELETE FROM moz_favicons WHERE id IN (
SELECT id FROM moz_favicons f
WHERE NOT EXISTS
(SELECT id FROM moz_places WHERE favicon_id = f.id LIMIT 1)
)`);
cleanupStatements.push(deleteOrphanIcons);
// MOZ_HISTORYVISITS
// F.1 remove orphan visits
let deleteOrphanVisits = DBConn.createAsyncStatement(
"DELETE FROM moz_historyvisits WHERE id IN (" +
"SELECT id FROM moz_historyvisits v " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_places WHERE id = v.place_id LIMIT 1) " +
")");
`DELETE FROM moz_historyvisits WHERE id IN (
SELECT id FROM moz_historyvisits v
WHERE NOT EXISTS
(SELECT id FROM moz_places WHERE id = v.place_id LIMIT 1)
)`);
cleanupStatements.push(deleteOrphanVisits);
// MOZ_INPUTHISTORY
// G.1 remove orphan input history
let deleteOrphanInputHistory = DBConn.createAsyncStatement(
"DELETE FROM moz_inputhistory WHERE place_id IN (" +
"SELECT place_id FROM moz_inputhistory i " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_places WHERE id = i.place_id LIMIT 1) " +
")");
`DELETE FROM moz_inputhistory WHERE place_id IN (
SELECT place_id FROM moz_inputhistory i
WHERE NOT EXISTS
(SELECT id FROM moz_places WHERE id = i.place_id LIMIT 1)
)`);
cleanupStatements.push(deleteOrphanInputHistory);
// MOZ_ITEMS_ANNOS
// H.1 remove item annos with an invalid attribute
let deleteInvalidAttributeItemsAnnos = DBConn.createAsyncStatement(
"DELETE FROM moz_items_annos WHERE id IN ( " +
"SELECT id FROM moz_items_annos t " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_anno_attributes " +
"WHERE id = t.anno_attribute_id LIMIT 1) " +
")");
`DELETE FROM moz_items_annos WHERE id IN (
SELECT id FROM moz_items_annos t
WHERE NOT EXISTS
(SELECT id FROM moz_anno_attributes
WHERE id = t.anno_attribute_id LIMIT 1)
)`);
cleanupStatements.push(deleteInvalidAttributeItemsAnnos);
// H.2 remove orphan item annos
let deleteOrphanItemsAnnos = DBConn.createAsyncStatement(
"DELETE FROM moz_items_annos WHERE id IN ( " +
"SELECT id FROM moz_items_annos t " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_bookmarks WHERE id = t.item_id LIMIT 1) " +
")");
`DELETE FROM moz_items_annos WHERE id IN (
SELECT id FROM moz_items_annos t
WHERE NOT EXISTS
(SELECT id FROM moz_bookmarks WHERE id = t.item_id LIMIT 1)
)`);
cleanupStatements.push(deleteOrphanItemsAnnos);
// MOZ_KEYWORDS
// I.1 remove unused keywords
let deleteUnusedKeywords = DBConn.createAsyncStatement(
"DELETE FROM moz_keywords WHERE id IN ( " +
"SELECT id FROM moz_keywords k " +
"WHERE NOT EXISTS " +
"(SELECT id FROM moz_bookmarks WHERE keyword_id = k.id LIMIT 1) " +
")");
`DELETE FROM moz_keywords WHERE id IN (
SELECT id FROM moz_keywords k
WHERE NOT EXISTS
(SELECT id FROM moz_bookmarks WHERE keyword_id = k.id LIMIT 1)
)`);
cleanupStatements.push(deleteUnusedKeywords);
// MOZ_PLACES
// L.1 fix wrong favicon ids
let fixInvalidFaviconIds = DBConn.createAsyncStatement(
"UPDATE moz_places SET favicon_id = NULL WHERE id IN ( " +
"SELECT id FROM moz_places h " +
"WHERE favicon_id NOT NULL " +
"AND NOT EXISTS " +
"(SELECT id FROM moz_favicons WHERE id = h.favicon_id LIMIT 1) " +
")");
`UPDATE moz_places SET favicon_id = NULL WHERE id IN (
SELECT id FROM moz_places h
WHERE favicon_id NOT NULL
AND NOT EXISTS
(SELECT id FROM moz_favicons WHERE id = h.favicon_id LIMIT 1)
)`);
cleanupStatements.push(fixInvalidFaviconIds);
// L.2 recalculate visit_count and last_visit_date
let fixVisitStats = DBConn.createAsyncStatement(
"UPDATE moz_places " +
"SET visit_count = (SELECT count(*) FROM moz_historyvisits " +
"WHERE place_id = moz_places.id AND visit_type NOT IN (0,4,7,8)), " +
"last_visit_date = (SELECT MAX(visit_date) FROM moz_historyvisits " +
"WHERE place_id = moz_places.id) " +
"WHERE id IN ( " +
"SELECT h.id FROM moz_places h " +
"WHERE visit_count <> (SELECT count(*) FROM moz_historyvisits v " +
"WHERE v.place_id = h.id AND visit_type NOT IN (0,4,7,8)) " +
"OR last_visit_date <> (SELECT MAX(visit_date) FROM moz_historyvisits v " +
"WHERE v.place_id = h.id) " +
")");
`UPDATE moz_places
SET visit_count = (SELECT count(*) FROM moz_historyvisits
WHERE place_id = moz_places.id AND visit_type NOT IN (0,4,7,8)),
last_visit_date = (SELECT MAX(visit_date) FROM moz_historyvisits
WHERE place_id = moz_places.id)
WHERE id IN (
SELECT h.id FROM moz_places h
WHERE visit_count <> (SELECT count(*) FROM moz_historyvisits v
WHERE v.place_id = h.id AND visit_type NOT IN (0,4,7,8))
OR last_visit_date <> (SELECT MAX(visit_date) FROM moz_historyvisits v
WHERE v.place_id = h.id)
)`);
cleanupStatements.push(fixVisitStats);
// L.3 recalculate hidden for redirects.
let fixRedirectsHidden = DBConn.createAsyncStatement(
"UPDATE moz_places " +
"SET hidden = 1 " +
"WHERE id IN ( " +
"SELECT h.id FROM moz_places h " +
"JOIN moz_historyvisits src ON src.place_id = h.id " +
"JOIN moz_historyvisits dst ON dst.from_visit = src.id AND dst.visit_type IN (5,6) " +
"LEFT JOIN moz_bookmarks on fk = h.id AND fk ISNULL " +
"GROUP BY src.place_id HAVING count(*) = visit_count " +
")");
`UPDATE moz_places
SET hidden = 1
WHERE id IN (
SELECT h.id FROM moz_places h
JOIN moz_historyvisits src ON src.place_id = h.id
JOIN moz_historyvisits dst ON dst.from_visit = src.id AND dst.visit_type IN (5,6)
LEFT JOIN moz_bookmarks on fk = h.id AND fk ISNULL
GROUP BY src.place_id HAVING count(*) = visit_count
)`);
cleanupStatements.push(fixRedirectsHidden);
// L.4 recalculate foreign_count.
let fixForeignCount = DBConn.createAsyncStatement(
"UPDATE moz_places SET foreign_count = " +
"(SELECT count(*) FROM moz_bookmarks WHERE fk = moz_places.id )");
`UPDATE moz_places SET foreign_count =
(SELECT count(*) FROM moz_bookmarks WHERE fk = moz_places.id )`);
cleanupStatements.push(fixForeignCount);
// MAINTENANCE STATEMENTS SHOULD GO ABOVE THIS POINT!
@ -798,7 +798,7 @@ this.PlacesDBUtils = {
while (stmt.executeStep()) {
let tableName = stmt.getString(0);
let countStmt = DBConn.createStatement(
"SELECT count(*) FROM " + tableName);
`SELECT count(*) FROM ${tableName}`);
countStmt.executeStep();
tasks.log("Table " + tableName + " has " + countStmt.getInt32(0) + " records");
countStmt.finalize();
@ -871,47 +871,47 @@ this.PlacesDBUtils = {
{ histogram: "PLACES_BOOKMARKS_COUNT",
healthreport: true,
query: "SELECT count(*) FROM moz_bookmarks b "
+ "JOIN moz_bookmarks t ON t.id = b.parent "
+ "AND t.parent <> :tags_folder "
+ "WHERE b.type = :type_bookmark " },
query: `SELECT count(*) FROM moz_bookmarks b
JOIN moz_bookmarks t ON t.id = b.parent
AND t.parent <> :tags_folder
WHERE b.type = :type_bookmark` },
{ histogram: "PLACES_TAGS_COUNT",
query: "SELECT count(*) FROM moz_bookmarks "
+ "WHERE parent = :tags_folder " },
query: `SELECT count(*) FROM moz_bookmarks
WHERE parent = :tags_folder` },
{ histogram: "PLACES_FOLDERS_COUNT",
query: "SELECT count(*) FROM moz_bookmarks "
+ "WHERE TYPE = :type_folder "
+ "AND parent NOT IN (0, :places_root, :tags_folder) " },
query: `SELECT count(*) FROM moz_bookmarks
WHERE TYPE = :type_folder
AND parent NOT IN (0, :places_root, :tags_folder)` },
{ histogram: "PLACES_KEYWORDS_COUNT",
query: "SELECT count(*) FROM moz_keywords " },
query: "SELECT count(*) FROM moz_keywords" },
{ histogram: "PLACES_SORTED_BOOKMARKS_PERC",
query: "SELECT IFNULL(ROUND(( "
+ "SELECT count(*) FROM moz_bookmarks b "
+ "JOIN moz_bookmarks t ON t.id = b.parent "
+ "AND t.parent <> :tags_folder AND t.parent > :places_root "
+ "WHERE b.type = :type_bookmark "
+ ") * 100 / ( "
+ "SELECT count(*) FROM moz_bookmarks b "
+ "JOIN moz_bookmarks t ON t.id = b.parent "
+ "AND t.parent <> :tags_folder "
+ "WHERE b.type = :type_bookmark "
+ ")), 0) " },
query: `SELECT IFNULL(ROUND((
SELECT count(*) FROM moz_bookmarks b
JOIN moz_bookmarks t ON t.id = b.parent
AND t.parent <> :tags_folder AND t.parent > :places_root
WHERE b.type = :type_bookmark
) * 100 / (
SELECT count(*) FROM moz_bookmarks b
JOIN moz_bookmarks t ON t.id = b.parent
AND t.parent <> :tags_folder
WHERE b.type = :type_bookmark
)), 0)` },
{ histogram: "PLACES_TAGGED_BOOKMARKS_PERC",
query: "SELECT IFNULL(ROUND(( "
+ "SELECT count(*) FROM moz_bookmarks b "
+ "JOIN moz_bookmarks t ON t.id = b.parent "
+ "AND t.parent = :tags_folder "
+ ") * 100 / ( "
+ "SELECT count(*) FROM moz_bookmarks b "
+ "JOIN moz_bookmarks t ON t.id = b.parent "
+ "AND t.parent <> :tags_folder "
+ "WHERE b.type = :type_bookmark "
+ ")), 0) " },
query: `SELECT IFNULL(ROUND((
SELECT count(*) FROM moz_bookmarks b
JOIN moz_bookmarks t ON t.id = b.parent
AND t.parent = :tags_folder
) * 100 / (
SELECT count(*) FROM moz_bookmarks b
JOIN moz_bookmarks t ON t.id = b.parent
AND t.parent <> :tags_folder
WHERE b.type = :type_bookmark
)), 0)` },
{ histogram: "PLACES_DATABASE_FILESIZE_MB",
callback: function () {

View File

@ -1330,9 +1330,9 @@ this.PlacesUtils = {
let itemIds = [];
Task.spawn(function* () {
let conn = yield this.promiseDBConnection();
const QUERY_STR = "SELECT b.id FROM moz_bookmarks b " +
"JOIN moz_places h on h.id = b.fk " +
"WHERE h.url = :url";
const QUERY_STR = `SELECT b.id FROM moz_bookmarks b
JOIN moz_places h on h.id = b.fk
WHERE h.url = :url`;
let spec = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
yield conn.executeCached(QUERY_STR, { url: spec }, aRow => {
if (abort)
@ -1694,38 +1694,38 @@ this.PlacesUtils = {
};
const QUERY_STR =
"WITH RECURSIVE " +
"descendants(fk, level, type, id, guid, parent, parentGUID, position, " +
" title, dateAdded, lastModified) AS (" +
" SELECT b1.fk, 0, b1.type, b1.id, b1.guid, b1.parent, " +
" (SELECT guid FROM moz_bookmarks WHERE id = b1.parent), " +
" b1.position, b1.title, b1.dateAdded, b1.lastModified " +
" FROM moz_bookmarks b1 WHERE b1.guid=:item_guid " +
" UNION ALL " +
" SELECT b2.fk, level + 1, b2.type, b2.id, b2.guid, b2.parent, " +
" descendants.guid, b2.position, b2.title, b2.dateAdded, " +
" b2.lastModified " +
" FROM moz_bookmarks b2 " +
" JOIN descendants ON b2.parent = descendants.id AND b2.id <> :tags_folder) " +
"SELECT d.level, d.id, d.guid, d.parent, d.parentGUID, d.type, " +
" d.position AS [index], d.title, d.dateAdded, d.lastModified, " +
" h.url, f.url AS iconuri, " +
" (SELECT GROUP_CONCAT(t.title, ',') " +
" FROM moz_bookmarks b2 " +
" JOIN moz_bookmarks t ON t.id = +b2.parent AND t.parent = :tags_folder " +
" WHERE b2.fk = h.id " +
" ) AS tags, " +
" EXISTS (SELECT 1 FROM moz_items_annos " +
" WHERE item_id = d.id LIMIT 1) AS has_annos, " +
" (SELECT a.content FROM moz_annos a " +
" JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id " +
" WHERE place_id = h.id AND n.name = :charset_anno " +
" ) AS charset " +
"FROM descendants d " +
"LEFT JOIN moz_bookmarks b3 ON b3.id = d.parent " +
"LEFT JOIN moz_places h ON h.id = d.fk " +
"LEFT JOIN moz_favicons f ON f.id = h.favicon_id " +
"ORDER BY d.level, d.parent, d.position";
`WITH RECURSIVE
descendants(fk, level, type, id, guid, parent, parentGUID, position,
title, dateAdded, lastModified) AS (
SELECT b1.fk, 0, b1.type, b1.id, b1.guid, b1.parent,
(SELECT guid FROM moz_bookmarks WHERE id = b1.parent),
b1.position, b1.title, b1.dateAdded, b1.lastModified
FROM moz_bookmarks b1 WHERE b1.guid=:item_guid
UNION ALL
SELECT b2.fk, level + 1, b2.type, b2.id, b2.guid, b2.parent,
descendants.guid, b2.position, b2.title, b2.dateAdded,
b2.lastModified
FROM moz_bookmarks b2
JOIN descendants ON b2.parent = descendants.id AND b2.id <> :tags_folder)
SELECT d.level, d.id, d.guid, d.parent, d.parentGUID, d.type,
d.position AS [index], d.title, d.dateAdded, d.lastModified,
h.url, f.url AS iconuri,
(SELECT GROUP_CONCAT(t.title, ',')
FROM moz_bookmarks b2
JOIN moz_bookmarks t ON t.id = +b2.parent AND t.parent = :tags_folder
WHERE b2.fk = h.id
) AS tags,
EXISTS (SELECT 1 FROM moz_items_annos
WHERE item_id = d.id LIMIT 1) AS has_annos,
(SELECT a.content FROM moz_annos a
JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id
WHERE place_id = h.id AND n.name = :charset_anno
) AS charset
FROM descendants d
LEFT JOIN moz_bookmarks b3 ON b3.id = d.parent
LEFT JOIN moz_places h ON h.id = d.fk
LEFT JOIN moz_favicons f ON f.id = h.favicon_id
ORDER BY d.level, d.parent, d.position`;
if (!aItemGUID)

View File

@ -73,21 +73,21 @@ LivemarkService.prototype = {
get _populateCacheSQL()
{
function getAnnoSQLFragment(aAnnoParam) {
return "SELECT a.content "
+ "FROM moz_items_annos a "
+ "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
+ "WHERE a.item_id = b.id "
+ "AND n.name = " + aAnnoParam;
return `SELECT a.content
FROM moz_items_annos a
JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id
WHERE a.item_id = b.id
AND n.name = ${aAnnoParam}`;
}
return "SELECT b.id, b.title, b.parent, b.position, b.guid, b.lastModified, "
+ "(" + getAnnoSQLFragment(":feedURI_anno") + ") AS feedURI, "
+ "(" + getAnnoSQLFragment(":siteURI_anno") + ") AS siteURI "
+ "FROM moz_bookmarks b "
+ "JOIN moz_items_annos a ON a.item_id = b.id "
+ "JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id "
+ "WHERE b.type = :folder_type "
+ "AND n.name = :feedURI_anno ";
return `SELECT b.id, b.title, b.parent, b.position, b.guid, b.lastModified,
( ${getAnnoSQLFragment(":feedURI_anno")} ) AS feedURI,
( ${getAnnoSQLFragment(":siteURI_anno")} ) AS siteURI
FROM moz_bookmarks b
JOIN moz_items_annos a ON a.item_id = b.id
JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id
WHERE b.type = :folder_type
AND n.name = :feedURI_anno`;
},
_ensureAsynchronousCache: Task.async(function* () {

View File

@ -25,17 +25,17 @@ const Cr = Components.results;
// - the bookmark title, if it is a bookmark (kQueryIndexBookmarkTitle)
// - the tags associated with a bookmarked entry (kQueryIndexTags)
const kBookTagSQLFragment =
"EXISTS(SELECT 1 FROM moz_bookmarks WHERE fk = h.id) AS bookmarked, "
+ "( "
+ "SELECT title FROM moz_bookmarks WHERE fk = h.id AND title NOTNULL "
+ "ORDER BY lastModified DESC LIMIT 1 "
+ ") AS btitle, "
+ "( "
+ "SELECT GROUP_CONCAT(t.title, ',') "
+ "FROM moz_bookmarks b "
+ "JOIN moz_bookmarks t ON t.id = +b.parent AND t.parent = :parent "
+ "WHERE b.fk = h.id "
+ ") AS tags";
`EXISTS(SELECT 1 FROM moz_bookmarks WHERE fk = h.id) AS bookmarked,
(
SELECT title FROM moz_bookmarks WHERE fk = h.id AND title NOTNULL
ORDER BY lastModified DESC LIMIT 1
) AS btitle,
(
SELECT GROUP_CONCAT(t.title, ',')
FROM moz_bookmarks b
JOIN moz_bookmarks t ON t.id = +b.parent AND t.parent = :parent
WHERE b.fk = h.id
) AS tags`;
// observer topics
const kTopicShutdown = "places-shutdown";
@ -105,10 +105,10 @@ function initTempTable(aDatabase)
// Note: this should be kept up-to-date with the definition in
// nsPlacesTables.h.
let stmt = aDatabase.createAsyncStatement(
"CREATE TEMP TABLE moz_openpages_temp ( "
+ " url TEXT PRIMARY KEY "
+ ", open_count INTEGER "
+ ") "
`CREATE TEMP TABLE moz_openpages_temp (
url TEXT PRIMARY KEY
, open_count INTEGER
)`
);
stmt.executeAsync();
stmt.finalize();
@ -116,13 +116,13 @@ function initTempTable(aDatabase)
// Note: this should be kept up-to-date with the definition in
// nsPlacesTriggers.h.
stmt = aDatabase.createAsyncStatement(
"CREATE TEMPORARY TRIGGER moz_openpages_temp_afterupdate_trigger "
+ "AFTER UPDATE OF open_count ON moz_openpages_temp FOR EACH ROW "
+ "WHEN NEW.open_count = 0 "
+ "BEGIN "
+ "DELETE FROM moz_openpages_temp "
+ "WHERE url = NEW.url; "
+ "END "
`CREATE TEMPORARY TRIGGER moz_openpages_temp_afterupdate_trigger
AFTER UPDATE OF open_count ON moz_openpages_temp FOR EACH ROW
WHEN NEW.open_count = 0
BEGIN
DELETE FROM moz_openpages_temp
WHERE url = NEW.url;
END`
);
stmt.executeAsync();
stmt.finalize();
@ -286,21 +286,24 @@ function nsPlacesAutoComplete()
// TODO bug 412736 in case of a frecency tie, break it with h.typed and
// h.visit_count which is better than nothing. This is slow, so not doing it
// yet...
const SQL_BASE = "SELECT h.url, h.title, f.url, " + kBookTagSQLFragment + ", "
+ "h.visit_count, h.typed, h.id, :query_type, "
+ "t.open_count "
+ "FROM moz_places h "
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
+ "LEFT JOIN moz_openpages_temp t ON t.url = h.url "
+ "WHERE h.frecency <> 0 "
+ "AND AUTOCOMPLETE_MATCH(:searchString, h.url, "
+ "IFNULL(btitle, h.title), tags, "
+ "h.visit_count, h.typed, "
+ "bookmarked, t.open_count, "
+ ":matchBehavior, :searchBehavior) "
+ "{ADDITIONAL_CONDITIONS} "
+ "ORDER BY h.frecency DESC, h.id DESC "
+ "LIMIT :maxResults";
function baseQuery(conditions = "") {
let query = `SELECT h.url, h.title, f.url, ${kBookTagSQLFragment},
h.visit_count, h.typed, h.id, :query_type,
t.open_count
FROM moz_places h
LEFT JOIN moz_favicons f ON f.id = h.favicon_id
LEFT JOIN moz_openpages_temp t ON t.url = h.url
WHERE h.frecency <> 0
AND AUTOCOMPLETE_MATCH(:searchString, h.url,
IFNULL(btitle, h.title), tags,
h.visit_count, h.typed,
bookmarked, t.open_count,
:matchBehavior, :searchBehavior)
${conditions}
ORDER BY h.frecency DESC, h.id DESC
LIMIT :maxResults`;
return query;
}
//////////////////////////////////////////////////////////////////////////////
//// Smart Getters
@ -343,128 +346,113 @@ function nsPlacesAutoComplete()
});
XPCOMUtils.defineLazyGetter(this, "_defaultQuery", function() {
let replacementText = "";
return this._db.createAsyncStatement(
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
);
return this._db.createAsyncStatement(baseQuery());
});
XPCOMUtils.defineLazyGetter(this, "_historyQuery", function() {
// Enforce ignoring the visit_count index, since the frecency one is much
// faster in this case. ANALYZE helps the query planner to figure out the
// faster path, but it may not have run yet.
let replacementText = "AND +h.visit_count > 0";
return this._db.createAsyncStatement(
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
);
return this._db.createAsyncStatement(baseQuery("AND +h.visit_count > 0"));
});
XPCOMUtils.defineLazyGetter(this, "_bookmarkQuery", function() {
let replacementText = "AND bookmarked";
return this._db.createAsyncStatement(
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
);
return this._db.createAsyncStatement(baseQuery("AND bookmarked"));
});
XPCOMUtils.defineLazyGetter(this, "_tagsQuery", function() {
let replacementText = "AND tags IS NOT NULL";
return this._db.createAsyncStatement(
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
);
return this._db.createAsyncStatement(baseQuery("AND tags IS NOT NULL"));
});
XPCOMUtils.defineLazyGetter(this, "_openPagesQuery", function() {
return this._db.createAsyncStatement(
"SELECT t.url, t.url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "
+ ":query_type, t.open_count, NULL "
+ "FROM moz_openpages_temp t "
+ "LEFT JOIN moz_places h ON h.url = t.url "
+ "WHERE h.id IS NULL "
+ "AND AUTOCOMPLETE_MATCH(:searchString, t.url, t.url, NULL, "
+ "NULL, NULL, NULL, t.open_count, "
+ ":matchBehavior, :searchBehavior) "
+ "ORDER BY t.ROWID DESC "
+ "LIMIT :maxResults "
`SELECT t.url, t.url, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
:query_type, t.open_count, NULL
FROM moz_openpages_temp t
LEFT JOIN moz_places h ON h.url = t.url
WHERE h.id IS NULL
AND AUTOCOMPLETE_MATCH(:searchString, t.url, t.url, NULL,
NULL, NULL, NULL, t.open_count,
:matchBehavior, :searchBehavior)
ORDER BY t.ROWID DESC
LIMIT :maxResults`
);
});
XPCOMUtils.defineLazyGetter(this, "_typedQuery", function() {
let replacementText = "AND h.typed = 1";
return this._db.createAsyncStatement(
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
);
return this._db.createAsyncStatement(baseQuery("AND h.typed = 1"));
});
XPCOMUtils.defineLazyGetter(this, "_adaptiveQuery", function() {
return this._db.createAsyncStatement(
"/* do not warn (bug 487789) */ "
+ "SELECT h.url, h.title, f.url, " + kBookTagSQLFragment + ", "
+ "h.visit_count, h.typed, h.id, :query_type, t.open_count "
+ "FROM ( "
+ "SELECT ROUND( "
+ "MAX(use_count) * (1 + (input = :search_string)), 1 "
+ ") AS rank, place_id "
+ "FROM moz_inputhistory "
+ "WHERE input BETWEEN :search_string AND :search_string || X'FFFF' "
+ "GROUP BY place_id "
+ ") AS i "
+ "JOIN moz_places h ON h.id = i.place_id "
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
+ "LEFT JOIN moz_openpages_temp t ON t.url = h.url "
+ "WHERE AUTOCOMPLETE_MATCH(NULL, h.url, "
+ "IFNULL(btitle, h.title), tags, "
+ "h.visit_count, h.typed, bookmarked, "
+ "t.open_count, "
+ ":matchBehavior, :searchBehavior) "
+ "ORDER BY rank DESC, h.frecency DESC "
`/* do not warn (bug 487789) */
SELECT h.url, h.title, f.url, ${kBookTagSQLFragment},
h.visit_count, h.typed, h.id, :query_type, t.open_count
FROM (
SELECT ROUND(
MAX(use_count) * (1 + (input = :search_string)), 1
) AS rank, place_id
FROM moz_inputhistory
WHERE input BETWEEN :search_string AND :search_string || X'FFFF'
GROUP BY place_id
) AS i
JOIN moz_places h ON h.id = i.place_id
LEFT JOIN moz_favicons f ON f.id = h.favicon_id
LEFT JOIN moz_openpages_temp t ON t.url = h.url
WHERE AUTOCOMPLETE_MATCH(NULL, h.url,
IFNULL(btitle, h.title), tags,
h.visit_count, h.typed, bookmarked,
t.open_count,
:matchBehavior, :searchBehavior)
ORDER BY rank DESC, h.frecency DESC`
);
});
XPCOMUtils.defineLazyGetter(this, "_keywordQuery", function() {
return this._db.createAsyncStatement(
"/* do not warn (bug 487787) */ "
+ "SELECT "
+ "(SELECT REPLACE(url, '%s', :query_string) FROM moz_places WHERE id = b.fk) "
+ "AS search_url, h.title, "
+ "IFNULL(f.url, (SELECT f.url "
+ "FROM moz_places "
+ "JOIN moz_favicons f ON f.id = favicon_id "
+ "WHERE rev_host = (SELECT rev_host FROM moz_places WHERE id = b.fk) "
+ "ORDER BY frecency DESC "
+ "LIMIT 1) "
+ "), 1, b.title, NULL, h.visit_count, h.typed, IFNULL(h.id, b.fk), "
+ ":query_type, t.open_count "
+ "FROM moz_keywords k "
+ "JOIN moz_bookmarks b ON b.keyword_id = k.id "
+ "LEFT JOIN moz_places h ON h.url = search_url "
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
+ "LEFT JOIN moz_openpages_temp t ON t.url = search_url "
+ "WHERE LOWER(k.keyword) = LOWER(:keyword) "
+ "ORDER BY h.frecency DESC "
`/* do not warn (bug 487787) */
SELECT
(SELECT REPLACE(url, '%s', :query_string) FROM moz_places WHERE id = b.fk)
AS search_url, h.title,
IFNULL(f.url, (SELECT f.url
FROM moz_places
JOIN moz_favicons f ON f.id = favicon_id
WHERE rev_host = (SELECT rev_host FROM moz_places WHERE id = b.fk)
ORDER BY frecency DESC
LIMIT 1)
), 1, b.title, NULL, h.visit_count, h.typed, IFNULL(h.id, b.fk),
:query_type, t.open_count
FROM moz_keywords k
JOIN moz_bookmarks b ON b.keyword_id = k.id
LEFT JOIN moz_places h ON h.url = search_url
LEFT JOIN moz_favicons f ON f.id = h.favicon_id
LEFT JOIN moz_openpages_temp t ON t.url = search_url
WHERE LOWER(k.keyword) = LOWER(:keyword)
ORDER BY h.frecency DESC`
);
});
this._registerOpenPageQuerySQL = "INSERT OR REPLACE INTO moz_openpages_temp "
+ "(url, open_count) "
+ "VALUES (:page_url, "
+ "IFNULL("
+ "("
+ "SELECT open_count + 1 "
+ "FROM moz_openpages_temp "
+ "WHERE url = :page_url "
+ "), "
+ "1"
+ ")"
+ ")";
this._registerOpenPageQuerySQL =
`INSERT OR REPLACE INTO moz_openpages_temp (url, open_count)
VALUES (:page_url,
IFNULL(
(
SELECT open_count + 1
FROM moz_openpages_temp
WHERE url = :page_url
),
1
)
)`;
XPCOMUtils.defineLazyGetter(this, "_registerOpenPageQuery", function() {
return this._db.createAsyncStatement(this._registerOpenPageQuerySQL);
});
XPCOMUtils.defineLazyGetter(this, "_unregisterOpenPageQuery", function() {
return this._db.createAsyncStatement(
"UPDATE moz_openpages_temp "
+ "SET open_count = open_count - 1 "
+ "WHERE url = :page_url"
`UPDATE moz_openpages_temp
SET open_count = open_count - 1
WHERE url = :page_url`
);
});
@ -1290,14 +1278,14 @@ urlInlineComplete.prototype = {
// Add a trailing slash at the end of the hostname, since we always
// want to complete up to and including a URL separator.
this.__hostQuery = this._db.createAsyncStatement(
"/* do not warn (bug no): could index on (typed,frecency) but not worth it */ "
+ "SELECT host || '/', prefix || host || '/' "
+ "FROM moz_hosts "
+ "WHERE host BETWEEN :search_string AND :search_string || X'FFFF' "
+ "AND frecency <> 0 "
+ (this._autofillTyped ? "AND typed = 1 " : "")
+ "ORDER BY frecency DESC "
+ "LIMIT 1"
`/* do not warn (bug no): could index on (typed,frecency) but not worth it */
SELECT host || '/', prefix || host || '/'
FROM moz_hosts
WHERE host BETWEEN :search_string AND :search_string || X'FFFF'
AND frecency <> 0
${this._autofillTyped ? "AND typed = 1" : ""}
ORDER BY frecency DESC
LIMIT 1`
);
}
return this.__hostQuery;
@ -1309,17 +1297,17 @@ urlInlineComplete.prototype = {
{
if (!this.__urlQuery) {
this.__urlQuery = this._db.createAsyncStatement(
"/* do not warn (bug no): can't use an index */ "
+ "SELECT h.url "
+ "FROM moz_places h "
+ "WHERE h.frecency <> 0 "
+ (this._autofillTyped ? "AND h.typed = 1 " : "")
+ "AND AUTOCOMPLETE_MATCH(:searchString, h.url, "
+ "h.title, '', "
+ "h.visit_count, h.typed, 0, 0, "
+ ":matchBehavior, :searchBehavior) "
+ "ORDER BY h.frecency DESC, h.id DESC "
+ "LIMIT 1"
`/* do not warn (bug no): can't use an index */
SELECT h.url
FROM moz_places h
WHERE h.frecency <> 0
${this._autofillTyped ? "AND h.typed = 1 " : ""}
AND AUTOCOMPLETE_MATCH(:searchString, h.url,
h.title, '',
h.visit_count, h.typed, 0, 0,
:matchBehavior, :searchBehavior)
ORDER BY h.frecency DESC, h.id DESC
LIMIT 1`
);
}
return this.__urlQuery;

View File

@ -171,24 +171,24 @@ const EXPIRATION_QUERIES = {
// This explicitly excludes any visits added in the last 7 days, to protect
// users with thousands of bookmarks from constantly losing history.
QUERY_FIND_VISITS_TO_EXPIRE: {
sql: "INSERT INTO expiration_notify "
+ "(v_id, url, guid, visit_date, expected_results) "
+ "SELECT v.id, h.url, h.guid, v.visit_date, :limit_visits "
+ "FROM moz_historyvisits v "
+ "JOIN moz_places h ON h.id = v.place_id "
+ "WHERE (SELECT COUNT(*) FROM moz_places) > :max_uris "
+ "AND visit_date < strftime('%s','now','localtime','start of day','-7 days','utc') * 1000000 "
+ "ORDER BY v.visit_date ASC "
+ "LIMIT :limit_visits",
sql: `INSERT INTO expiration_notify
(v_id, url, guid, visit_date, expected_results)
SELECT v.id, h.url, h.guid, v.visit_date, :limit_visits
FROM moz_historyvisits v
JOIN moz_places h ON h.id = v.place_id
WHERE (SELECT COUNT(*) FROM moz_places) > :max_uris
AND visit_date < strftime('%s','now','localtime','start of day','-7 days','utc') * 1000000
ORDER BY v.visit_date ASC
LIMIT :limit_visits`,
actions: ACTION.TIMED_OVERLIMIT | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
// Removes the previously found visits.
QUERY_EXPIRE_VISITS: {
sql: "DELETE FROM moz_historyvisits WHERE id IN ( "
+ "SELECT v_id FROM expiration_notify WHERE v_id NOTNULL "
+ ")",
sql: `DELETE FROM moz_historyvisits WHERE id IN (
SELECT v_id FROM expiration_notify WHERE v_id NOTNULL
)`,
actions: ACTION.TIMED_OVERLIMIT | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
},
@ -201,51 +201,51 @@ const EXPIRATION_QUERIES = {
// before it actually gets the new visit or bookmark.
// Thus, since new pages get frecency -1, we filter on that.
QUERY_FIND_URIS_TO_EXPIRE: {
sql: "INSERT INTO expiration_notify "
+ "(p_id, url, guid, visit_date, expected_results) "
+ "SELECT h.id, h.url, h.guid, h.last_visit_date, :limit_uris "
+ "FROM moz_places h "
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
+ "WHERE h.last_visit_date IS NULL "
+ "AND h.foreign_count = 0 "
+ "AND v.id IS NULL "
+ "AND frecency <> -1 "
+ "LIMIT :limit_uris",
sql: `INSERT INTO expiration_notify
(p_id, url, guid, visit_date, expected_results)
SELECT h.id, h.url, h.guid, h.last_visit_date, :limit_uris
FROM moz_places h
LEFT JOIN moz_historyvisits v ON h.id = v.place_id
WHERE h.last_visit_date IS NULL
AND h.foreign_count = 0
AND v.id IS NULL
AND frecency <> -1
LIMIT :limit_uris`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire found URIs from the database.
QUERY_EXPIRE_URIS: {
sql: "DELETE FROM moz_places WHERE id IN ( "
+ "SELECT p_id FROM expiration_notify WHERE p_id NOTNULL "
+ ")",
sql: `DELETE FROM moz_places WHERE id IN (
SELECT p_id FROM expiration_notify WHERE p_id NOTNULL
)`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire orphan URIs from the database.
QUERY_SILENT_EXPIRE_ORPHAN_URIS: {
sql: "DELETE FROM moz_places WHERE id IN ( "
+ "SELECT h.id "
+ "FROM moz_places h "
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
+ "WHERE h.last_visit_date IS NULL "
+ "AND h.foreign_count = 0 "
+ "AND v.id IS NULL "
+ "LIMIT :limit_uris "
+ ")",
sql: `DELETE FROM moz_places WHERE id IN (
SELECT h.id
FROM moz_places h
LEFT JOIN moz_historyvisits v ON h.id = v.place_id
WHERE h.last_visit_date IS NULL
AND h.foreign_count = 0
AND v.id IS NULL
LIMIT :limit_uris
)`,
actions: ACTION.CLEAR_HISTORY
},
// Expire orphan icons from the database.
QUERY_EXPIRE_FAVICONS: {
sql: "DELETE FROM moz_favicons WHERE id IN ( "
+ "SELECT f.id FROM moz_favicons f "
+ "LEFT JOIN moz_places h ON f.id = h.favicon_id "
+ "WHERE h.favicon_id IS NULL "
+ "LIMIT :limit_favicons "
+ ")",
sql: `DELETE FROM moz_favicons WHERE id IN (
SELECT f.id FROM moz_favicons f
LEFT JOIN moz_places h ON f.id = h.favicon_id
WHERE h.favicon_id IS NULL
LIMIT :limit_favicons
)`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
@ -253,12 +253,12 @@ const EXPIRATION_QUERIES = {
// Expire orphan page annotations from the database.
QUERY_EXPIRE_ANNOS: {
sql: "DELETE FROM moz_annos WHERE id in ( "
+ "SELECT a.id FROM moz_annos a "
+ "LEFT JOIN moz_places h ON a.place_id = h.id "
+ "WHERE h.id IS NULL "
+ "LIMIT :limit_annos "
+ ")",
sql: `DELETE FROM moz_annos WHERE id in (
SELECT a.id FROM moz_annos a
LEFT JOIN moz_places h ON a.place_id = h.id
WHERE h.id IS NULL
LIMIT :limit_annos
)`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
@ -266,13 +266,13 @@ const EXPIRATION_QUERIES = {
// Expire page annotations based on expiration policy.
QUERY_EXPIRE_ANNOS_WITH_POLICY: {
sql: "DELETE FROM moz_annos "
+ "WHERE (expiration = :expire_days "
+ "AND :expire_days_time > MAX(lastModified, dateAdded)) "
+ "OR (expiration = :expire_weeks "
+ "AND :expire_weeks_time > MAX(lastModified, dateAdded)) "
+ "OR (expiration = :expire_months "
+ "AND :expire_months_time > MAX(lastModified, dateAdded))",
sql: `DELETE FROM moz_annos
WHERE (expiration = :expire_days
AND :expire_days_time > MAX(lastModified, dateAdded))
OR (expiration = :expire_weeks
AND :expire_weeks_time > MAX(lastModified, dateAdded))
OR (expiration = :expire_months
AND :expire_months_time > MAX(lastModified, dateAdded))`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
@ -280,13 +280,13 @@ const EXPIRATION_QUERIES = {
// Expire items annotations based on expiration policy.
QUERY_EXPIRE_ITEMS_ANNOS_WITH_POLICY: {
sql: "DELETE FROM moz_items_annos "
+ "WHERE (expiration = :expire_days "
+ "AND :expire_days_time > MAX(lastModified, dateAdded)) "
+ "OR (expiration = :expire_weeks "
+ "AND :expire_weeks_time > MAX(lastModified, dateAdded)) "
+ "OR (expiration = :expire_months "
+ "AND :expire_months_time > MAX(lastModified, dateAdded))",
sql: `DELETE FROM moz_items_annos
WHERE (expiration = :expire_days
AND :expire_days_time > MAX(lastModified, dateAdded))
OR (expiration = :expire_weeks
AND :expire_weeks_time > MAX(lastModified, dateAdded))
OR (expiration = :expire_months
AND :expire_months_time > MAX(lastModified, dateAdded))`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
@ -294,10 +294,10 @@ const EXPIRATION_QUERIES = {
// Expire page annotations based on expiration policy.
QUERY_EXPIRE_ANNOS_WITH_HISTORY: {
sql: "DELETE FROM moz_annos "
+ "WHERE expiration = :expire_with_history "
+ "AND NOT EXISTS (SELECT id FROM moz_historyvisits "
+ "WHERE place_id = moz_annos.place_id LIMIT 1)",
sql: `DELETE FROM moz_annos
WHERE expiration = :expire_with_history
AND NOT EXISTS (SELECT id FROM moz_historyvisits
WHERE place_id = moz_annos.place_id LIMIT 1)`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
@ -305,37 +305,37 @@ const EXPIRATION_QUERIES = {
// Expire item annos without a corresponding item id.
QUERY_EXPIRE_ITEMS_ANNOS: {
sql: "DELETE FROM moz_items_annos WHERE id IN ( "
+ "SELECT a.id FROM moz_items_annos a "
+ "LEFT JOIN moz_bookmarks b ON a.item_id = b.id "
+ "WHERE b.id IS NULL "
+ "LIMIT :limit_annos "
+ ")",
sql: `DELETE FROM moz_items_annos WHERE id IN (
SELECT a.id FROM moz_items_annos a
LEFT JOIN moz_bookmarks b ON a.item_id = b.id
WHERE b.id IS NULL
LIMIT :limit_annos
)`,
actions: ACTION.CLEAR_HISTORY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire all annotation names without a corresponding annotation.
QUERY_EXPIRE_ANNO_ATTRIBUTES: {
sql: "DELETE FROM moz_anno_attributes WHERE id IN ( "
+ "SELECT n.id FROM moz_anno_attributes n "
+ "LEFT JOIN moz_annos a ON n.id = a.anno_attribute_id "
+ "LEFT JOIN moz_items_annos t ON n.id = t.anno_attribute_id "
+ "WHERE a.anno_attribute_id IS NULL "
+ "AND t.anno_attribute_id IS NULL "
+ "LIMIT :limit_annos"
+ ")",
sql: `DELETE FROM moz_anno_attributes WHERE id IN (
SELECT n.id FROM moz_anno_attributes n
LEFT JOIN moz_annos a ON n.id = a.anno_attribute_id
LEFT JOIN moz_items_annos t ON n.id = t.anno_attribute_id
WHERE a.anno_attribute_id IS NULL
AND t.anno_attribute_id IS NULL
LIMIT :limit_annos
)`,
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY |
ACTION.IDLE_DAILY | ACTION.DEBUG
},
// Expire orphan inputhistory.
QUERY_EXPIRE_INPUTHISTORY: {
sql: "DELETE FROM moz_inputhistory WHERE place_id IN ( "
+ "SELECT i.place_id FROM moz_inputhistory i "
+ "LEFT JOIN moz_places h ON h.id = i.place_id "
+ "WHERE h.id IS NULL "
+ "LIMIT :limit_inputhistory "
+ ")",
sql: `DELETE FROM moz_inputhistory WHERE place_id IN (
SELECT i.place_id FROM moz_inputhistory i
LEFT JOIN moz_places h ON h.id = i.place_id
WHERE h.id IS NULL
LIMIT :limit_inputhistory
)`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
ACTION.DEBUG
@ -357,11 +357,11 @@ const EXPIRATION_QUERIES = {
// If p_id is set whole_entry = 1, then we have expired the full page.
// Either p_id or v_id are always set.
QUERY_SELECT_NOTIFICATIONS: {
sql: "SELECT url, guid, MAX(visit_date) AS visit_date, "
+ "MAX(IFNULL(MIN(p_id, 1), MIN(v_id, 0))) AS whole_entry, "
+ "expected_results "
+ "FROM expiration_notify "
+ "GROUP BY url",
sql: `SELECT url, guid, MAX(visit_date) AS visit_date,
MAX(IFNULL(MIN(p_id, 1), MIN(v_id, 0))) AS whole_entry,
expected_results
FROM expiration_notify
GROUP BY url`,
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
},
@ -415,15 +415,15 @@ function nsPlacesExpiration()
// Create the temporary notifications table.
let stmt = db.createAsyncStatement(
"CREATE TEMP TABLE expiration_notify ( "
+ " id INTEGER PRIMARY KEY "
+ ", v_id INTEGER "
+ ", p_id INTEGER "
+ ", url TEXT NOT NULL "
+ ", guid TEXT NOT NULL "
+ ", visit_date INTEGER "
+ ", expected_results INTEGER NOT NULL "
+ ") ");
`CREATE TEMP TABLE expiration_notify (
id INTEGER PRIMARY KEY
, v_id INTEGER
, p_id INTEGER
, url TEXT NOT NULL
, guid TEXT NOT NULL
, visit_date INTEGER
, expected_results INTEGER NOT NULL
)`);
stmt.executeAsync();
stmt.finalize();
@ -793,9 +793,9 @@ nsPlacesExpiration.prototype = {
_getPagesStats: function PEX__getPagesStats(aCallback) {
if (!this._cachedStatements["LIMIT_COUNT"]) {
this._cachedStatements["LIMIT_COUNT"] = this._db.createAsyncStatement(
"SELECT (SELECT COUNT(*) FROM moz_places), "
+ "(SELECT SUBSTR(stat,1,LENGTH(stat)-2) FROM sqlite_stat1 "
+ "WHERE idx = 'moz_places_url_uniqueindex')"
`SELECT (SELECT COUNT(*) FROM moz_places),
(SELECT SUBSTR(stat,1,LENGTH(stat)-2) FROM sqlite_stat1
WHERE idx = 'moz_places_url_uniqueindex')`
);
}
this._cachedStatements["LIMIT_COUNT"].executeAsync({

View File

@ -62,9 +62,9 @@ TaggingService.prototype = {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let stmt = db.createStatement(
"SELECT id FROM moz_bookmarks "
+ "WHERE parent = :tag_id "
+ "AND fk = (SELECT id FROM moz_places WHERE url = :page_url)"
`SELECT id FROM moz_bookmarks
WHERE parent = :tag_id
AND fk = (SELECT id FROM moz_places WHERE url = :page_url)`
);
stmt.params.tag_id = tagId;
stmt.params.page_url = aURI.spec;
@ -181,8 +181,8 @@ TaggingService.prototype = {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let stmt = db.createStatement(
"SELECT count(*) AS count FROM moz_bookmarks "
+ "WHERE parent = :tag_id"
`SELECT count(*) AS count FROM moz_bookmarks
WHERE parent = :tag_id`
);
stmt.params.tag_id = aTagId;
try {
@ -247,9 +247,9 @@ TaggingService.prototype = {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let stmt = db.createStatement(
"SELECT h.url FROM moz_places h "
+ "JOIN moz_bookmarks b ON b.fk = h.id "
+ "WHERE b.parent = :tag_id "
`SELECT h.url FROM moz_places h
JOIN moz_bookmarks b ON b.fk = h.id
WHERE b.parent = :tag_id`
);
stmt.params.tag_id = tagId;
try {
@ -358,9 +358,9 @@ TaggingService.prototype = {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let stmt = db.createStatement(
"SELECT id, parent "
+ "FROM moz_bookmarks "
+ "WHERE fk = (SELECT id FROM moz_places WHERE url = :page_url)"
`SELECT id, parent
FROM moz_bookmarks
WHERE fk = (SELECT id FROM moz_places WHERE url = :page_url)`
);
stmt.params.page_url = aURI.spec;
try {