Merge lp:~stolowski/unity-scope-click/fix-1352451 into lp:unity-scope-click/devel

Proposed by Paweł Stołowski
Status: Merged
Approved by: Alejandro J. Cura
Approved revision: 395
Merged at revision: 390
Proposed branch: lp:~stolowski/unity-scope-click/fix-1352451
Merge into: lp:unity-scope-click/devel
Diff against target: 275 lines (+108/-24)
10 files modified
data/CMakeLists.txt (+5/-0)
data/click-scope-departments-db.conf.in (+6/-1)
data/update_schema.sh (+55/-0)
debian/unity-scope-click-departmentsdb.install (+1/-0)
libclickscope/click/departments-db.cpp (+18/-15)
libclickscope/tests/test_departments-db.cpp (+4/-1)
libclickscope/tests/test_interface.cpp (+2/-0)
scope/clickapps/apps-query.cpp (+13/-5)
scope/tests/test_apps_query.cpp (+1/-1)
scope/tests/test_query.cpp (+3/-1)
To merge this branch: bzr merge lp:~stolowski/unity-scope-click/fix-1352451
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+229669@code.launchpad.net

Commit message

Remove depts_v. Store department mappings for top-level departments in depts table. Bump schema to version 2 and provide schema_update.sh script executed with the upstart job. Update default departments db.

Description of the change

The problem this MR solves has a few causes - in the order of importance:
* the root "All" department (with empty id) didn't really exist in the database (in particular in 'depts' table, which keeps the hierarchy of departments). Instead, we had a depts_v view which returned virtual root for all top level departments. However, the SQL that populated that view was problematic, as it had to do a 'join' against deptnames *without* a locale restriction, and therefore it was "picking" entries for the department names of the fallback empty locale ("").
* the department names for a "fallback" empty locale would never get updated, since the shell always gives us correct locale name, such as en_US, and we update db records for those. The entries for "" locale contained departments such as '3d'.

What this MR does:
* it bumps db schema to version 2
* it provides the new default departments db.
* it removes the problematic depts_v. Instead, the depts table now contains real mappings also for top-level departments (e.g. "accessories" is a child of ""). This eliminates the problem of joining with deptnames: the depts table contains complete hierarchy.
* it provides a script for updating schema. This script gets rid of the department names for "" locale, removes depts_v and inserts missing mappings for root departments into detps.
* the update_schema.sh script doesn't remove obsolete departments, such as 3d, but it fixes the root cause that kept that department around even though it was gone in the store. Visiting Ubuntu store scope will re-sync departments db and remove any obsolete departments.

Note: make sure you reboot after updating click scope from this branch. The update-schema.sh script is required to be executed which normally happens during start of unity8 session.

Testing:
Ideally, this branch should be tested by updating an existing image with new click scope (and rebooting), and by testing a "first-boot" experience (use --wipe, or remove /home/phablet/.cache/click-departments.db while click scope is not running + reboot).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
393. By Paweł Stołowski

Merged devel.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
394. By Paweł Stołowski

Don't fail if name for a single subdepartment is missing, just ignore it.

395. By Paweł Stołowski

Insert names for top-level departments in the update schema script.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Code looks good. Will test on the device shortly.

Revision history for this message
Alejandro J. Cura (alecu) wrote :

Seems to be working fine on the device.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/CMakeLists.txt'
2--- data/CMakeLists.txt 2014-07-14 16:53:54 +0000
3+++ data/CMakeLists.txt 2014-08-06 17:40:43 +0000
4@@ -45,6 +45,11 @@
5 )
6
7 install(
8+ PROGRAMS update_schema.sh
9+ DESTINATION "${APPS_DATA_DIR}"
10+)
11+
12+install(
13 FILES "${CMAKE_CURRENT_BINARY_DIR}/${STORE_INI_TARGET}"
14 DESTINATION "${STORE_LIB_DIR}"
15 )
16
17=== modified file 'data/click-scope-departments-db.conf.in'
18--- data/click-scope-departments-db.conf.in 2014-07-14 16:21:26 +0000
19+++ data/click-scope-departments-db.conf.in 2014-08-06 17:40:43 +0000
20@@ -5,5 +5,10 @@
21
22 script
23 DB_FILE=@APPS_DATA_DIR@/departments.db
24- [ -f $HOME/.cache/click-departments.db ] || cp $DB_FILE $HOME/.cache/click-departments.db
25+ if [ -f $HOME/.cache/click-departments.db ]
26+ then
27+ @APPS_DATA_DIR@/update_schema.sh $HOME/.cache/click-departments.db
28+ else
29+ cp $DB_FILE $HOME/.cache/click-departments.db
30+ fi
31 end script
32
33=== modified file 'data/departments.db'
34Binary files data/departments.db 2014-07-15 14:15:37 +0000 and data/departments.db 2014-08-06 17:40:43 +0000 differ
35=== added file 'data/update_schema.sh'
36--- data/update_schema.sh 1970-01-01 00:00:00 +0000
37+++ data/update_schema.sh 2014-08-06 17:40:43 +0000
38@@ -0,0 +1,55 @@
39+#!/bin/sh
40+DBFILE=$1
41+
42+if [ -z "$DBFILE" ]
43+then
44+ echo "Usage: $0 <departments db file>"
45+ exit 1
46+fi
47+
48+if [ ! -w "$DBFILE" ]
49+then
50+ echo "Cannot open $DBFILE for writing"
51+ exit 2
52+fi
53+
54+SCHEMA_VERSION=$(sqlite3 "$DBFILE" "SELECT value FROM meta WHERE name='version'")
55+
56+##############################################
57+# Update departments db from version 1 to 2
58+##############################################
59+if [ "x$SCHEMA_VERSION" = "x1" ]
60+then
61+ # updating deptnames may fail if en_US is already there, in such case just delete entries for empty locale
62+ sqlite3 "$DBFILE" "UPDATE deptnames SET locale='en_US' WHERE locale=''" || sqlite3 "$DBFILE" "DELETE FROM deptnames WHERE locale=''"
63+ sqlite3 "$DBFILE" << _UPDATE_TO_VER2
64+
65+ INSERT INTO deptnames (deptid,locale,name) VALUES ('universal-access','en_US','Universal Access');
66+ INSERT INTO deptnames (deptid,locale,name) VALUES ('office','en_US','Office');
67+ INSERT INTO deptnames (deptid,locale,name) VALUES ('graphics','en_US','Graphics');
68+ INSERT INTO deptnames (deptid,locale,name) VALUES ('science-engineering','en_US','Science & Engineering');
69+ INSERT INTO deptnames (deptid,locale,name) VALUES ('internet','en_US','Internet');
70+ INSERT INTO deptnames (deptid,locale,name) VALUES ('accessories','en_US','Accessories');
71+ INSERT INTO deptnames (deptid,locale,name) VALUES ('developer-tools','en_US','Developer Tools');
72+ INSERT INTO deptnames (deptid,locale,name) VALUES ('games','en_US','Games');
73+ INSERT INTO deptnames (deptid,locale,name) VALUES ('books-magazines','en_US','Books & Magazines');
74+ INSERT INTO deptnames (deptid,locale,name) VALUES ('education','en_US','Education');
75+ INSERT INTO deptnames (deptid,locale,name) VALUES ('sound-video','en_US','Sound & Video');
76+
77+ BEGIN TRANSACTION;
78+ DROP VIEW depts_v;
79+ INSERT INTO depts (deptid,parentid) VALUES ('universal-access','');
80+ INSERT INTO depts (deptid,parentid) VALUES ('office','');
81+ INSERT INTO depts (deptid,parentid) VALUES ('graphics','');
82+ INSERT INTO depts (deptid,parentid) VALUES ('science-engineering','');
83+ INSERT INTO depts (deptid,parentid) VALUES ('internet','');
84+ INSERT INTO depts (deptid,parentid) VALUES ('accessories','');
85+ INSERT INTO depts (deptid,parentid) VALUES ('developer-tools','');
86+ INSERT INTO depts (deptid,parentid) VALUES ('games','');
87+ INSERT INTO depts (deptid,parentid) VALUES ('books-magazines','');
88+ INSERT INTO depts (deptid,parentid) VALUES ('education','');
89+ INSERT INTO depts (deptid,parentid) VALUES ('sound-video','');
90+ UPDATE meta SET value='2' WHERE name='version';
91+ END TRANSACTION;
92+_UPDATE_TO_VER2
93+fi
94
95=== modified file 'debian/unity-scope-click-departmentsdb.install'
96--- debian/unity-scope-click-departmentsdb.install 2014-07-14 16:53:54 +0000
97+++ debian/unity-scope-click-departmentsdb.install 2014-08-06 17:40:43 +0000
98@@ -1,2 +1,3 @@
99 usr/share/unity/scopes/clickapps/departments.db
100+usr/share/unity/scopes/clickapps/update_schema.sh
101 usr/share/upstart/sessions/*.conf
102
103=== modified file 'libclickscope/click/departments-db.cpp'
104--- libclickscope/click/departments-db.cpp 2014-07-22 20:07:28 +0000
105+++ libclickscope/click/departments-db.cpp 2014-08-06 17:40:43 +0000
106@@ -94,10 +94,10 @@
107 insert_dept_id_query_->prepare("INSERT OR REPLACE INTO depts (deptid, parentid) VALUES (:deptid, :parentid)");
108 insert_dept_name_query_->prepare("INSERT OR REPLACE INTO deptnames (deptid, locale, name) VALUES (:deptid, :locale, :name)");
109 select_pkgs_by_dept_->prepare("SELECT pkgid FROM pkgmap WHERE deptid=:deptid");
110- select_pkgs_by_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts_v WHERE deptid=:deptid UNION SELECT depts_v.deptid FROM recdepts,depts_v WHERE recdepts.deptid=depts_v.parentid) SELECT pkgid FROM pkgmap NATURAL JOIN recdepts");
111+ select_pkgs_by_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT pkgid FROM pkgmap NATURAL JOIN recdepts");
112 select_pkg_by_pkgid_->prepare("SELECT pkgid FROM pkgmap WHERE pkgid=:pkgid");
113- select_children_depts_->prepare("SELECT deptid,(SELECT COUNT(1) from DEPTS_V AS inner WHERE inner.parentid=outer.deptid) FROM DEPTS_V AS outer WHERE parentid=:parentid");
114- select_parent_dept_->prepare("SELECT parentid FROM depts_v WHERE deptid=:deptid");
115+ select_children_depts_->prepare("SELECT deptid,(SELECT COUNT(1) from depts AS inner WHERE inner.parentid=outer.deptid) FROM depts AS outer WHERE parentid=:parentid");
116+ select_parent_dept_->prepare("SELECT parentid FROM depts WHERE deptid=:deptid");
117 select_dept_name_->prepare("SELECT name FROM deptnames WHERE deptid=:deptid AND locale=:locale");
118 }
119
120@@ -107,6 +107,11 @@
121
122 void DepartmentsDb::init_db()
123 {
124+ //
125+ // CAUTION:
126+ // DON'T FORGET TO BUMP SCHEMA VERSION BELOW AND HANDLE SCHEMA UPGRADE IN data/update_schema.sh
127+ // WHENEVER YOU CHANGE ANY OF THE TABLES BELOW!
128+
129 QSqlQuery query;
130
131 // FIXME: for some reason enabling foreign keys gives errors about number of arguments of prepared queries when doing query.exec(); do not enable
132@@ -141,14 +146,11 @@
133 {
134 report_db_error(query.lastError(), "Failed to create meta table");
135 }
136- query.exec("INSERT INTO meta (name, value) VALUES ('version', 1)");
137
138- // view of the depts table that automatically adds fake "" department for root departments
139- if (!query.exec("CREATE VIEW IF NOT EXISTS depts_v AS SELECT deptid, parentid FROM depts UNION SELECT deptid,'' AS parentid FROM deptnames WHERE NOT EXISTS "
140- "(SELECT * FROM depts WHERE depts.deptid=deptnames.deptid)"))
141- {
142- report_db_error(query.lastError(), "Failed to create depts_v view");
143- }
144+ //
145+ // note: this will fail due to unique constraint, but that's fine; it's expected to succeed only when new database is created; in other
146+ // cases the version needs to be bumped in the update_schema.sh script.
147+ query.exec("INSERT INTO meta (name, value) VALUES ('version', 2)");
148
149 if (!db_.commit())
150 {
151@@ -304,11 +306,6 @@
152 throw std::logic_error("Invalid empty department id");
153 }
154
155- if (parent_department_id.empty())
156- {
157- throw std::logic_error("Invalid empty parent department id");
158- }
159-
160 insert_dept_id_query_->bindValue(":deptid", QVariant(QString::fromStdString(department_id)));
161 insert_dept_id_query_->bindValue(":parentid", QVariant(QString::fromStdString(parent_department_id)));
162 if (!insert_dept_id_query_->exec())
163@@ -408,6 +405,12 @@
164 delete_deptnames_query_->finish();
165 delete_depts_query_->finish();
166
167+ // store mapping of top level departments to root ""
168+ for (auto const& dept: depts)
169+ {
170+ store_department_mapping(dept->id(), "");
171+ }
172+
173 store_departments_(depts, locale);
174
175 if (!db_.commit())
176
177=== modified file 'libclickscope/tests/test_departments-db.cpp'
178--- libclickscope/tests/test_departments-db.cpp 2014-07-23 14:53:10 +0000
179+++ libclickscope/tests/test_departments-db.cpp 2014-08-06 17:40:43 +0000
180@@ -68,6 +68,10 @@
181 void SetUp() override
182 {
183 db.reset(new DepartmentsDbCheck(db_path, true));
184+
185+ db->store_department_mapping("tools", "");
186+ db->store_department_mapping("games", "");
187+
188 db->store_department_name("tools", "", "Tools");
189 db->store_department_name("office", "", "Office");
190
191@@ -230,7 +234,6 @@
192 EXPECT_THROW(db->store_department_name("", "", "Foo"), std::logic_error);
193 EXPECT_THROW(db->store_department_name("foo", "", ""), std::logic_error);
194 EXPECT_THROW(db->store_department_mapping("", "foo"), std::logic_error);
195- EXPECT_THROW(db->store_department_mapping("foo", ""), std::logic_error);
196 EXPECT_THROW(db->store_package_mapping("", "foo"), std::logic_error);
197 EXPECT_THROW(db->store_package_mapping("foo", ""), std::logic_error);
198 }
199
200=== modified file 'libclickscope/tests/test_interface.cpp'
201--- libclickscope/tests/test_interface.cpp 2014-07-21 12:41:31 +0000
202+++ libclickscope/tests/test_interface.cpp 2014-08-06 17:40:43 +0000
203@@ -222,6 +222,8 @@
204
205 depts_db->store_department_name("utilities", "", "Utilities");
206 depts_db->store_department_name("accessories", "", "Accessories");
207+ depts_db->store_department_mapping("utilities", "");
208+ depts_db->store_department_mapping("accessories", "");
209
210 auto results = iface.find_installed_apps("", "utilies", depts_db);
211 EXPECT_EQ(0, results.size());
212
213=== modified file 'scope/clickapps/apps-query.cpp'
214--- scope/clickapps/apps-query.cpp 2014-08-01 05:12:28 +0000
215+++ scope/clickapps/apps-query.cpp 2014-08-06 17:40:43 +0000
216@@ -294,7 +294,7 @@
217 void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy)
218 {
219 auto const current_dep_id = query().department_id();
220- const std::list<std::string> locales = { search_metadata().locale(), "en_US", "" };
221+ const std::list<std::string> locales = { search_metadata().locale(), "en_US" };
222
223 unity::scopes::Department::SPtr root;
224
225@@ -309,10 +309,18 @@
226 // attach subdepartments to it
227 for (auto const& subdep: impl->depts_db->get_children_departments(current_dep_id))
228 {
229- name = impl->depts_db->get_department_name(subdep.id, locales);
230- unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name);
231- dep->set_has_subdepartments(subdep.has_children);
232- current->add_subdepartment(dep);
233+ // if single supdepartment fails, then ignore it and continue with others
234+ try
235+ {
236+ name = impl->depts_db->get_department_name(subdep.id, locales);
237+ unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name);
238+ dep->set_has_subdepartments(subdep.has_children);
239+ current->add_subdepartment(dep);
240+ }
241+ catch (const std::exception &e)
242+ {
243+ qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what());
244+ }
245 }
246
247 // if current is not the top, then gets its parent
248
249=== modified file 'scope/tests/test_apps_query.cpp'
250--- scope/tests/test_apps_query.cpp 2014-08-01 05:09:06 +0000
251+++ scope/tests/test_apps_query.cpp 2014-08-06 17:40:43 +0000
252@@ -195,7 +195,7 @@
253 const std::vector<click::Application> installed_apps = {{"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", ""}};
254 const scopes::SearchMetadata metadata{"en_EN", "phone"};
255 const scopes::CategoryRenderer renderer{"{}"};
256- const std::list<std::string> expected_locales {"en_EN", "en_US", ""};
257+ const std::list<std::string> expected_locales {"en_EN", "en_US"};
258
259 };
260
261
262=== modified file 'scope/tests/test_query.cpp'
263--- scope/tests/test_query.cpp 2014-07-31 19:37:05 +0000
264+++ scope/tests/test_query.cpp 2014-08-06 17:40:43 +0000
265@@ -301,7 +301,9 @@
266 auto depts_db = std::make_shared<MockDepartmentsDb>(":memory:", true);
267
268 EXPECT_CALL(*depts_db, store_department_name(_, _, _)).Times(3);
269- EXPECT_CALL(*depts_db, store_department_mapping(_, _)).Times(2);
270+ EXPECT_CALL(*depts_db, store_department_mapping("1", ""));
271+ EXPECT_CALL(*depts_db, store_department_mapping("1-1", "1"));
272+ EXPECT_CALL(*depts_db, store_department_mapping("1-2", "1"));
273
274 MockIndex mock_index(click::Packages(), click::DepartmentList(), init_departments);
275 scopes::SearchMetadata metadata("en_EN", "phone");

Subscribers

People subscribed via source and target branches

to all changes: