summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
Diffstat (limited to 'db')
-rw-r--r--db/db_manager.py275
1 files changed, 138 insertions, 137 deletions
diff --git a/db/db_manager.py b/db/db_manager.py
index ad2fd14..9c2dd53 100644
--- a/db/db_manager.py
+++ b/db/db_manager.py
@@ -1,9 +1,18 @@
-import configparser
+"""
+db_manager exposes a DbManager class to make interacting with sqlite
+databases easier.
+"""
+import logging
import os
import sqlite3
+import six
-class DbManager:
+
+_LOGGER = logging.getLogger(__name__)
+
+class DbManager(object):
+ """DBManager makes interacting with sqlite databases easier."""
create_album_table = "CREATE TABLE IF NOT EXISTS album (id INTEGER "\
"PRIMARY KEY, name TEXT, date TEXT, musicbrainz_albumid TEXT)"
@@ -38,141 +47,133 @@ class DbManager:
create_track_number_index = "CREATE INDEX IF NOT EXISTS "\
"track_tracknumber_IDX ON track(tracknumber)"
- class __DbManager:
- config = configparser.ConfigParser()
- config.read("mach2.ini")
-
- def iterdump(connection):
- cu = connection.cursor()
- yield("BEGIN TRANSACTION;")
-
- q = """
- SELECT "name", "type", "sql"
- FROM "sqlite_master"
- WHERE "sql" NOT NULL AND
- "type" == 'table'
- ORDER BY "name";
- """
- schema_res = cu.execute(q).fetchall()
- for table_name, type, sql in schema_res:
- if table_name == "sqlite_sequence":
- yield("DELETE FROM \"sqlite_sequence\";")
- elif table_name == "sqlite_stat1":
- yield("ANALYZE \"sqlite_master\";")
- elif table_name.startswith("sqlite_"):
- continue
- else:
- yield("{0};".format(sql))
-
- table_name_ident = table_name.replace("\"", "\"\"")
- res = cu.execute("PRAGMA table_info(\"{0}\")".format(
- table_name_ident))
- column_names = [
- str(table_info[1]) for table_info in res.fetchall()]
- q = """
- SELECT 'INSERT INTO "{0}" VALUES({1})' FROM "{0}";
- """.format(table_name_ident, ",".join(
+ @staticmethod
+ def iterdump(connection):
+ """Iterates through the database, creating commands to dump all the
+ tables line by line."""
+ cursor = connection.cursor()
+
+ query = """
+ SELECT "name", "type", "sql"
+ FROM "sqlite_master"
+ WHERE "sql" NOT NULL AND
+ "type" == 'table'
+ ORDER BY "name";
+ """
+ schema_res = cursor.execute(query).fetchall()
+ for table_name, dummy, sql in schema_res:
+ if table_name == "sqlite_sequence":
+ yield "DELETE FROM \"sqlite_sequence\";"
+ elif table_name == "sqlite_stat1":
+ yield "ANALYZE \"sqlite_master\";"
+ elif table_name.startswith("sqlite_"):
+ continue
+ else:
+ yield six.u("{0};").format(sql)
+
+ table_name_ident = table_name.replace("\"", "\"\"")
+ res = cursor.execute("PRAGMA table_info(\"{0}\")".format(
+ table_name_ident))
+ column_names = [
+ str(table_info[1]) for table_info in res.fetchall()]
+ query = """
+ SELECT 'INSERT INTO "{0}" VALUES({1})' FROM "{0}";
+ """.format(table_name_ident, ",".join(
"""'||quote("{0}")||'""".format(
col.replace(
"\"", "\"\"")) for col in column_names))
- query_res = cu.execute(q)
- for row in query_res:
- yield("{0};".format(row[0]))
-
- q = """
- SELECT "name", "type", "sql"
- FROM "sqlite_master"
- WHERE "sql" NOT NULL AND
- "type" IN ('index', 'trigger', 'view')
- """
- schema_res = cu.execute(q)
- for name, type, sql in schema_res.fetchall():
- yield("{0};".format(sql))
-
- yield("COMMIT;")
-
- def __init__(self, db=None):
- new_db = False
- cache_size_kb = 9766
-
- if db:
- self.conn = sqlite3.connect(db)
-
- else:
- if not os.path.isfile(self.config["DEFAULT"]["database"]):
- new_db = True
-
- if new_db:
- self.conn = sqlite3.connect(":memory:")
- self.create_tables()
- else:
- self.conn = sqlite3.connect(
- self.config["DEFAULT"]["database"])
- library_info = os.stat(self.config["DEFAULT"]["database"])
- cache_size_kb = round((library_info.st_size * 1.2) / 1024)
-
- cursor = self.conn.cursor()
- # Setting pragma with ? placeholder produces an error
- cursor.execute("pragma cache_size=-%s" % cache_size_kb)
- cursor.close()
-
- self.conn.row_factory = sqlite3.Row
-
- def export(self):
- if not os.path.isfile(self.config["DEFAULT"]["database"]):
- script = ""
-
- for line in DbManager.__DbManager.iterdump(self.conn):
- script = "\n".join((script, line))
-
- tempconn = sqlite3.connect(
- self.config["DEFAULT"]["database"])
- tempcur = tempconn.cursor()
-
- tempcur.executescript(script)
- tempcur.close()
-
- def __str__(self):
- return repr(self)
-
- def execute(self, script, parameters=None):
- if parameters:
- return self.conn.execute(script, parameters)
-
- return self.conn.execute(script)
-
- def commit(self):
- return self.conn.commit()
-
- def cursor(self):
- return self.conn.cursor()
-
- def close(self):
- return self.conn.close()
-
- def interrupt(self):
- return self.conn.interrupt()
-
- def create_tables(self):
- with self.conn:
- self.conn.execute(DbManager.create_album_table)
- self.conn.execute(DbManager.create_album_artist_table)
- self.conn.execute(DbManager.create_album_track_table)
- self.conn.execute(DbManager.create_artist_table)
- self.conn.execute(DbManager.create_artist_track_table)
- self.conn.execute(DbManager.create_track_table)
- self.conn.execute(DbManager.create_musicbrainz_artist_index)
- self.conn.execute(DbManager.create_track_filename_index)
- self.conn.execute(DbManager.create_track_grouping_index)
- self.conn.execute(DbManager.create_track_name_index)
- self.conn.execute(DbManager.create_track_number_index)
-
- instance = None
-
- def __new__(self, db=None):
- if db:
- return DbManager.__DbManager(db)
- elif not DbManager.instance:
- DbManager.instance = DbManager.__DbManager()
-
- return DbManager.instance
+ query_res = cursor.execute(query)
+ for row in query_res:
+ yield six.u("{0};").format(row[0])
+
+ query = """
+ SELECT "name", "type", "sql"
+ FROM "sqlite_master"
+ WHERE "sql" NOT NULL AND
+ "type" IN ('index', 'trigger', 'view')
+ """
+ schema_res = cursor.execute(query)
+ for dummy, dummy2, sql in schema_res.fetchall():
+ yield six.u("{0};").format(sql)
+
+ def __init__(self, db_file):
+ new_db = False
+ cache_size_kb = 9766
+ self.db_file = db_file
+
+ if not os.path.isfile(self.db_file):
+ new_db = True
+
+ if new_db:
+ self.conn = sqlite3.connect(":memory:")
+ self.create_tables()
+ else:
+ self.conn = sqlite3.connect(self.db_file)
+ library_info = os.stat(self.db_file)
+ cache_size_kb = round((library_info.st_size * 1.2) / 1024)
+
+ cursor = self.conn.cursor()
+ # Setting pragma with ? placeholder produces an error
+ cursor.execute("pragma cache_size=-%s" % cache_size_kb)
+ cursor.close()
+
+ self.conn.row_factory = sqlite3.Row
+
+ def export(self):
+ """Export the database."""
+ if not os.path.isfile(self.db_file):
+ tempconn = sqlite3.connect(self.db_file)
+ tempcur = tempconn.cursor()
+ tempcur.execute("PRAGMA journal_mode=WAL;")
+ tempcur.close()
+
+ try:
+ with tempconn:
+ for line in DbManager.iterdump(self.conn):
+ tempconn.execute(line)
+
+ except sqlite3.Error as exc:
+ _LOGGER.error(exc)
+
+ tempconn.close()
+
+ def __str__(self):
+ return repr(self)
+
+ def execute(self, script, parameters=None):
+ """Execute an sql statement"""
+ if parameters:
+ return self.conn.execute(script, parameters)
+
+ return self.conn.execute(script)
+
+ def commit(self):
+ """Commit the current transaction"""
+ return self.conn.commit()
+
+ def cursor(self):
+ """Create a cursor"""
+ return self.conn.cursor()
+
+ def close(self):
+ """Close the connection"""
+ return self.conn.close()
+
+ def interrupt(self):
+ """Interrupt the connection"""
+ return self.conn.interrupt()
+
+ def create_tables(self):
+ """Create the database tables"""
+ with self.conn:
+ self.conn.execute(DbManager.create_album_table)
+ self.conn.execute(DbManager.create_album_artist_table)
+ self.conn.execute(DbManager.create_album_track_table)
+ self.conn.execute(DbManager.create_artist_table)
+ self.conn.execute(DbManager.create_artist_track_table)
+ self.conn.execute(DbManager.create_track_table)
+ self.conn.execute(DbManager.create_musicbrainz_artist_index)
+ self.conn.execute(DbManager.create_track_filename_index)
+ self.conn.execute(DbManager.create_track_grouping_index)
+ self.conn.execute(DbManager.create_track_name_index)
+ self.conn.execute(DbManager.create_track_number_index)