3 from library import permissions
5 _catalogue_db_file = '/users/libcom/catalogue.db'
7 _book_category_table='book_categories'
8 _category_table = 'categories'
10 _checkout_db_file = '/users/libcom/checkout.db'
11 _checkout_table = 'checked_out'
12 _return_table = 'returned'
14 _checkout_table_creation = '''
15 CREATE TABLE IF NOT EXISTS checked_out
16 (id INTEGER UNIQUE, uwid STRING, date_out DATETIME DEFAULT current_timestamp);
18 CREATE TABLE IF NOT EXISTS returned
19 (id INTEGER, uwid STRING, date_out DATETIME, date_in DATETIME DEFAULT current_timestamp);
22 _book_table_creation = '''
23 CREATE TABLE IF NOT EXISTS books
24 (id INTEGER PRIMARY KEY AUTOINCREMENT,
25 isbn, lccn, title, subtitle, authors, edition,
26 publisher, publish_year, publish_month, publish_location,
27 pages, pagination, weight,
28 last_updated DATETIME DEFAULT current_timestamp,
29 deleted BOOLEAN DEFAULT 0);
31 CREATE TABLE IF NOT EXISTS categories
32 (cat_id INTEGER PRIMARY KEY, category STRING UNIQUE ON CONFLICT IGNORE);
34 CREATE TABLE IF NOT EXISTS book_categories
35 (id INTEGER, cat_id INTEGER);
38 columns = ['id', 'isbn', 'lccn',
39 'title', 'subtitle', 'authors', 'edition',
40 'publisher', 'publish year', 'publish month', 'publish location',
41 'pages', 'pagination', 'weight', 'last updated', 'deleted']
43 _book_trigger_creation = '''
45 CREATE TRIGGER IF NOT EXISTS update_books_time AFTER UPDATE ON books
47 UPDATE books SET last_updated = DATETIME('NOW') WHERE rowid = new.rowid;
50 CREATE TRIGGER IF NOT EXISTS delete_book AFTER DELETE ON books
52 DELETE FROM book_categories WHERE id = old.rowid;
55 CREATE TRIGGER IF NOT EXISTS delete_category AFTER DELETE ON categories
57 DELETE FROM book_categories WHERE cat_id = old.cat_id;
60 CREATE TRIGGER IF NOT EXISTS insert_book_category_time AFTER INSERT
63 UPDATE books SET last_updated = DATETIME('NOW') WHERE id = new.id;
67 #################################
68 # character escaping, etc for sql queries
69 #################################
71 return s.replace(" ","_").lower()
74 return '"' + str(v).strip().replace('"','""') + '"'
76 ###################################
78 ##################################
79 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
81 conn = sqlite3.connect(_catalogue_db_file)
85 for k,v in book.items():
87 cols.append(_colify(k))
88 vals.append(_stringify(v))
90 query = ("INSERT INTO "+_book_table+" ("+", ".join(cols)+") VALUES ("+
96 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
97 def updateBook(book, bookID):
99 Takes book attribute dictionary and a string representating the book ID
100 number, and returns updates the book accordingly
102 conn = sqlite3.connect(_catalogue_db_file)
105 for k,v in book.items():
106 updates.append(_colify(k)+"="+_stringify(v))
107 query = ("UPDATE "+_book_table+" SET " + ", ".join(updates)+" WHERE id = " +
114 conn = sqlite3.connect(_catalogue_db_file)
116 query = "SELECT * FROM "+_book_table+" WHERE deleted=0;"
118 books = [_query_to_book(b) for b in c]
122 def getBooksByCategory(cat):
124 Takes a string representating the category ID number, and returns
125 non-deleted books in that category
127 conn = sqlite3.connect(_catalogue_db_file)
129 query = ("SELECT "+",".join(map(_colify,columns))+" FROM "+_book_table+
130 " JOIN "+_book_category_table+
131 " USING (id) WHERE cat_id = :id AND deleted=0;")
133 books = [_query_to_book(b) for b in c]
137 def getRemovedBooks():
138 conn = sqlite3.connect(_catalogue_db_file)
140 query = "SELECT * FROM "+_book_table+" WHERE DELETED=1;"
142 books = [_query_to_book(b) for b in c]
146 def get_book(bookid):
147 conn = sqlite3.connect(_catalogue_db_file)
149 query = "SELECT * FROM "+_book_table+" WHERE id = "+str(bookid)+";"
151 book = _query_to_book(c.fetchone())
155 # removes book from catalogue
156 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
157 def removeBook(bookid):
158 conn = sqlite3.connect(_catalogue_db_file)
160 query = "UPDATE " +_book_table+ " SET deleted=1 WHERE id = "+str(bookid)+";"
165 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
166 def removeBooks(books):
167 conn = sqlite3.connect(_catalogue_db_file)
169 query1 = "UPDATE " +_book_table+ " SET deleted=1 WHERE id = :id;"
171 c.execute(query1, book)
175 # restores trashed books
176 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
177 def restoreBooks(books):
178 conn = sqlite3.connect(_catalogue_db_file)
180 query1 = "UPDATE " +_book_table+ " SET deleted=0 WHERE id = :id;"
182 c.execute(query1,book)
186 # fully deletes book from books table
187 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
188 def deleteBook(bookid):
189 conn = sqlite3.connect(_catalogue_db_file)
191 query = "DELETE FROM " +_book_table+ " WHERE id = "+str(bookid)+";"
196 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
197 def deleteBooks(books):
198 conn = sqlite3.connect(_catalogue_db_file)
200 query = "DELETE FROM " +_book_table+ " WHERE id = :id;"
202 c.execute(query, book)
206 def _query_to_book(book_query):
207 # Make a dict out of column name and query results.
208 # Empty entries return None, which are removed from the dict.
209 return dict(filter(lambda t:t[1], zip(columns,book_query)))
211 def _query_to_book_checkout(book_query):
212 # Make a dict out of column name and query results.
213 # Empty entries return None, which are removed from the dict.
214 b = _query_to_book(book_query)
215 b['uwid'] = book_query[-2]
216 b['date'] = book_query[-1]
219 #########################################
220 # Category related functions
221 ########################################
222 def getBookCategories(book):
223 conn = sqlite3.connect(_catalogue_db_file)
225 query = ("SELECT id,cat_id,category FROM "+_book_category_table+" JOIN "+
226 _category_table+" USING (cat_id) WHERE id = :id ;")
227 c.execute(query,book)
229 for book_id,cat_id,cat_name in c:
230 cats.append({'id':book_id, 'cat_id':cat_id, 'category':cat_name})
234 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
235 def categorizeBook(book, cats):
236 conn = sqlite3.connect(_catalogue_db_file)
238 query = ("INSERT OR IGNORE INTO "+_book_category_table+
239 " (id,cat_id) VALUES (?, ?);")
241 args = (book['id'],cat['id'])
242 c.execute(query,args)
246 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
247 def uncategorizeBook(book, cats):
248 conn = sqlite3.connect(_catalogue_db_file)
250 query = "DELETE FROM "+_book_category_table+" WHERE (id = ? AND cat_id = ?);"
252 args = (book['id'],cat['id'])
253 c.execute(query,args)
258 conn = sqlite3.connect(_catalogue_db_file)
260 query = "SELECT cat_id, category FROM "+_category_table+";"
264 cats.append({'id':cat_id, 'category':cat})
268 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
269 def addCategory(cat):
270 conn = sqlite3.connect(_catalogue_db_file)
272 query = ("INSERT OR IGNORE INTO "+_category_table+" (category) VALUES ("
273 +_stringify(cat)+");")
278 @permissions.check_permissions(permissions.PERMISSION_LIBCOM)
279 def deleteCategories(cats):
280 conn = sqlite3.connect(_catalogue_db_file)
282 query1 = "DELETE FROM " +_category_table+ " WHERE cat_id = :id;"
284 c.execute(query1, cat)
288 #########################################
289 # Book Checkout functions
290 #########################################
291 @permissions.check_permissions(permissions.PERMISSION_OFFICE)
292 def checkout_book(book_id, uwid):
293 conn = sqlite3.connect(_checkout_db_file)
295 query = "INSERT INTO " + _checkout_table + " (id, uwid) VALUES (?, ?);"
296 c.execute(query, (book_id, uwid))
300 @permissions.check_permissions(permissions.PERMISSION_OFFICE)
301 def return_book(book_id):
302 conn = sqlite3.connect(_checkout_db_file)
304 query = "SELECT uwid,date_out FROM "+ _checkout_table + " WHERE id = :id ;"
305 c.execute(query, {"id": book_id})
309 query = "INSERT INTO " + _return_table + " (id, uwid, date_out) VALUES (?, ?, ?);"
310 query2 = "DELETE FROM " + _checkout_table + " WHERE id= :id ;"
311 c.execute(query, (book_id, uwid, date_out))
312 c.execute(query2, {"id": book_id});
316 def get_checkedout_books():
318 retrieves checked out books. The returned books also have the fields
319 uwid: ID of person who signed out the book, and
320 date: date when the book was checked out
322 conn = sqlite3.connect(_catalogue_db_file)
324 query = 'ATTACH "' + _checkout_db_file + '" AS co'
326 query = ("SELECT "+",".join(map(_colify,columns))+",uwid,date_out FROM "+_book_table+
327 " JOIN co."+_checkout_table+
330 books = [_query_to_book_checkout(b) for b in c]
334 def get_onshelf_books():
336 retrieves checked out books. The returned books also have the fields
337 uwid: ID of person who signed out the book, and
338 date: date when the book was checked out
340 conn = sqlite3.connect(_catalogue_db_file)
342 query = 'ATTACH "' + _checkout_db_file + '" AS co'
344 query = ("SELECT "+",".join(map(_colify,columns))+" FROM "+_book_table+
345 " LEFT JOIN co."+_checkout_table+
346 " USING (id) WHERE uwid ISNULL;")
348 books = [_query_to_book(b) for b in c]
352 #########################################
353 # Database initialization
354 #########################################
355 def _createBooksTable():
356 conn = sqlite3.connect(_catalogue_db_file)
358 c.executescript(_book_table_creation)
362 def _createTriggers():
363 conn = sqlite3.connect(_catalogue_db_file)
365 c.executescript(_book_trigger_creation)
369 def _create_checkout_table():
370 conn = sqlite3.connect(_checkout_db_file)
372 c.executescript(_checkout_table_creation)
376 def initializeDatabase():
379 _create_checkout_table()