The phonebook database contains all the PBAP-specific data.
The following entity-relationship (ER) diagram shows the relationships among the tables in the phonebook database:
The database schema is specified in /db/phonebook.sql, which looks like this:
/* Turn foreign key constraints on */ PRAGMA foreign_keys = ON; /* Contacts */ CREATE TABLE contacts ( contact_id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT NOT NULL, fn TEXT NOT NULL, family_name TEXT NOT NULL, given_name TEXT NOT NULL, additional_names TEXT, honorific_prefixes TEXT, honorific_suffixes TEXT, sort_string TEXT, bday TEXT, geo_lat REAL, geo_long REAL, mailer TEXT, tz TEXT, title TEXT, role TEXT, org TEXT, note TEXT, rev TEXT, url TEXT, uid TEXT, prod_id TEXT, class TEXT ); /* Emails */ CREATE TABLE emails ( email_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE, email TEXT NOT NULL ); CREATE TABLE email_types ( email_type_id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL UNIQUE ); CREATE TABLE emails_types_rel ( email_id INTEGER NOT NULL REFERENCES emails ON DELETE CASCADE, email_type_id INTEGER NOT NULL REFERENCES email_types ); /* Telephone numbers */ CREATE TABLE telephone_numbers ( telephone_number_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE, number TEXT NOT NULL ); CREATE TABLE telephone_number_types ( telephone_number_type_id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL UNIQUE ); CREATE TABLE telephone_numbers_types_rel ( telephone_number_id INTEGER NOT NULL REFERENCES telephone_numbers ON DELETE CASCADE, telephone_number_type_id INTEGER NOT NULL REFERENCES telephone_number_types ); /* Addresses */ CREATE TABLE addresses ( address_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE, post_office_box TEXT, extended_address TEXT, street_address TEXT, locality TEXT, region TEXT, postal_code TEXT, country_name TEXT ); CREATE TABLE address_types ( address_type_id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL UNIQUE ); CREATE TABLE addresses_types_rel ( address_id INTEGER NOT NULL REFERENCES addresses ON DELETE CASCADE, address_type_id INTEGER NOT NULL REFERENCES address_types ); /* Nicknames */ CREATE TABLE nicknames ( nickname_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE, nickname TEXT NOT NULL ); /* Categories */ CREATE TABLE categories ( category_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE, category TEXT NOT NULL ); /* Photos */ CREATE TABLE photos ( photo_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE, photo_data BLOB, photo_uri TEXT, encoding_type TEXT, image_media_type TEXT ); /* Call Log */ CREATE TABLE calls ( call_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER REFERENCES contacts ON DELETE SET NULL, call_type_id INTEGER NOT NULL REFERENCES call_types, fn TEXT, number TEXT, time TEXT NOT NULL, duration INTEGER ); CREATE TABLE call_types ( call_type_id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT ); /******** VIEWS ********/ CREATE VIEW emails_view AS SELECT emails.email_id, emails.contact_id, emails.email, MAX(CASE WHEN email_types.type = 'PREF' THEN 1 ELSE 0 END) AS pref, MAX(CASE WHEN email_types.type = 'INTERNET' THEN 1 ELSE 0 END) AS internet FROM emails LEFT JOIN emails_types_rel ON emails.email_id = emails_types_rel.email_id LEFT JOIN email_types ON emails_types_rel.email_type_id = email_types.email_type_id GROUP BY emails.email_id ORDER BY pref DESC, emails.email_id DESC; CREATE VIEW telephone_numbers_view AS SELECT telephone_numbers.telephone_number_id, telephone_numbers.contact_id, telephone_numbers.number, MAX(CASE WHEN telephone_number_types.type = 'PREF' THEN 1 ELSE 0 END) AS pref, MAX(CASE WHEN telephone_number_types.type = 'HOME' THEN 1 ELSE 0 END) AS home, MAX(CASE WHEN telephone_number_types.type = 'WORK' THEN 1 ELSE 0 END) AS work, MAX(CASE WHEN telephone_number_types.type = 'VOICE' THEN 1 ELSE 0 END) AS voice, MAX(CASE WHEN telephone_number_types.type = 'FAX' THEN 1 ELSE 0 END) AS fax, MAX(CASE WHEN telephone_number_types.type = 'MSG' THEN 1 ELSE 0 END) AS msg, MAX(CASE WHEN telephone_number_types.type = 'CELL' THEN 1 ELSE 0 END) AS cell, MAX(CASE WHEN telephone_number_types.type = 'PAGER' THEN 1 ELSE 0 END) AS pager, MAX(CASE WHEN telephone_number_types.type = 'BBS' THEN 1 ELSE 0 END) AS bbs, MAX(CASE WHEN telephone_number_types.type = 'MODEM' THEN 1 ELSE 0 END) AS modem, MAX(CASE WHEN telephone_number_types.type = 'CAR' THEN 1 ELSE 0 END) AS car, MAX(CASE WHEN telephone_number_types.type = 'ISDN' THEN 1 ELSE 0 END) AS isdn, MAX(CASE WHEN telephone_number_types.type = 'VIDEO' THEN 1 ELSE 0 END) AS video FROM telephone_numbers LEFT JOIN telephone_numbers_types_rel ON telephone_numbers.telephone_number_id = telephone_numbers_types_rel.telephone_number_id LEFT JOIN telephone_number_types ON telephone_numbers_types_rel.telephone_number_type_id = telephone_number_types.telephone_number_type_id GROUP BY telephone_numbers.telephone_number_id ORDER BY pref DESC, telephone_numbers.telephone_number_id DESC; CREATE VIEW addresses_view AS SELECT addresses.address_id, addresses.contact_id, addresses.post_office_box, addresses.extended_address, addresses.street_address, addresses.locality, addresses.region, addresses.postal_code, addresses.country_name, MAX(CASE WHEN address_types.type = 'PREF' THEN 1 ELSE 0 END) AS pref, MAX(CASE WHEN address_types.type = 'HOME' THEN 1 ELSE 0 END) AS home, MAX(CASE WHEN address_types.type = 'WORK' THEN 1 ELSE 0 END) AS work, MAX(CASE WHEN address_types.type = 'DOM' THEN 1 ELSE 0 END) AS dom, MAX(CASE WHEN address_types.type = 'INTL' THEN 1 ELSE 0 END) AS intl, MAX(CASE WHEN address_types.type = 'POSTAL' THEN 1 ELSE 0 END) AS postal, MAX(CASE WHEN address_types.type = 'PARCEL' THEN 1 ELSE 0 END) AS parcel FROM addresses LEFT JOIN addresses_types_rel ON addresses.address_id = addresses_types_rel.address_id LEFT JOIN address_types ON addresses_types_rel.address_type_id = address_types.address_type_id GROUP BY addresses.address_id ORDER BY pref DESC, addresses.address_id DESC; CREATE VIEW contacts_view AS SELECT contacts.contact_id, contacts.honorific_prefixes AS title, contacts.family_name AS last_name, contacts.given_name AS first_name, contacts.bday AS birthday, NULL AS anniversary, contacts.org AS company, contacts.title AS job_title, home_phone_1.number as home_phone, home_phone_2.number as home_phone_2, work_phone_1.number as work_phone, work_phone_2.number as work_phone_2, mobile_phone.number as mobile_phone, pager_phone.number as pager_phone, fax_phone.number as fax_phone, other_phone.number as other_phone, email_1.email AS email_1, email_2.email AS email_2, email_3.email AS email_3, home_address.street_address AS home_address_1, home_address.extended_address AS home_address_2, home_address.locality AS home_address_city, home_address.country_name AS home_address_country, home_address.region AS home_address_state_province, home_address.postal_code AS home_address_zip_postal, work_address.street_address AS work_address_1, work_address.extended_address AS work_address_2, work_address.locality AS work_address_city, work_address.country_name AS work_address_country, work_address.region AS work_address_state_province, work_address.postal_code AS work_address_zip_postal, photos.photo_uri AS picture, NULL AS pin, contacts.uid AS uid, contacts.url AS web_page, (SELECT GROUP_CONCAT(categories.category) FROM categories WHERE categories.contact_id = contacts.contact_id) AS categories, contacts.note AS note, NULL AS user1, NULL AS user2, NULL AS user3, NULL AS user4 from contacts LEFT JOIN telephone_numbers_view home_phone_1 ON contacts.contact_id = home_phone_1.contact_id AND home_phone_1.home = 1 LEFT JOIN telephone_numbers_view home_phone_2 ON contacts.contact_id = home_phone_2.contact_id AND home_phone_2.home = 1 AND home_phone_2.telephone_number_id <> home_phone_1.telephone_number_id LEFT JOIN telephone_numbers_view work_phone_1 ON contacts.contact_id = work_phone_1.contact_id AND work_phone_1.work= 1 LEFT JOIN telephone_numbers_view work_phone_2 ON contacts.contact_id = work_phone_2.contact_id AND work_phone_2.work = 1 AND work_phone_2.telephone_number_id <> work_phone_1.telephone_number_id LEFT JOIN telephone_numbers_view mobile_phone ON contacts.contact_id = mobile_phone.contact_id AND mobile_phone.cell = 1 LEFT JOIN telephone_numbers_view pager_phone ON contacts.contact_id = pager_phone.contact_id AND pager_phone.pager = 1 LEFT JOIN telephone_numbers_view fax_phone ON contacts.contact_id = fax_phone.contact_id AND fax_phone.fax = 1 LEFT JOIN telephone_numbers_view other_phone ON contacts.contact_id = other_phone.contact_id AND other_phone.telephone_number_id NOT IN( COALESCE(home_phone_1.telephone_number_id, 0), COALESCE(home_phone_2.telephone_number_id, 0), COALESCE(work_phone_1.telephone_number_id, 0), COALESCE(work_phone_2.telephone_number_id, 0), COALESCE(mobile_phone.telephone_number_id, 0), COALESCE(pager_phone.telephone_number_id, 0), COALESCE(fax_phone.telephone_number_id, 0)) LEFT JOIN emails_view email_1 ON contacts.contact_id = email_1.contact_id LEFT JOIN emails_view email_2 ON contacts.contact_id = email_2.contact_id AND email_2.email_id <> email_1.email_id LEFT JOIN emails_view email_3 ON contacts.contact_id = email_3.contact_id AND email_3.email_id <> email_1.email_id AND email_3.email_id <> email_2.email_id LEFT JOIN addresses_view home_address ON contacts.contact_id = home_address.contact_id AND home_address.home = 1 LEFT JOIN addresses_view work_address ON contacts.contact_id = work_address.contact_id AND work_address.work = 1 LEFT JOIN photos ON contacts.contact_id = photos.contact_id WHERE 0=0 AND (CASE WHEN home_phone_2.telephone_number_id IS NOT NULL THEN home_phone_1.pref >= home_phone_2.pref ELSE 1 END) AND (CASE WHEN work_phone_2.telephone_number_id IS NOT NULL THEN work_phone_1.pref >= work_phone_2.pref ELSE 1 END) AND (CASE WHEN email_2.email_id IS NOT NULL THEN email_1.pref >= email_2.pref ELSE 1 END) AND (CASE WHEN email_3.email_id IS NOT NULL THEN email_1.pref >= email_3.pref ELSE 1 END) GROUP BY contacts.contact_id ORDER BY LOWER(last_name) ASC, LOWER(first_name) ASC;