Mercurial > libervia-backend
diff src/tools/sqlite.py @ 412:62b17854254e
database integration: first draft
- using SQLite as backend
/!\ Not finished yet, break execution. SàT CAN'T LAUNCH PROPERLY IN THE CURRENT STATE
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 30 Oct 2011 23:13:40 +0100 |
parents | |
children | dd4caab17008 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/sqlite.py Sun Oct 30 23:13:40 2011 +0100 @@ -0,0 +1,136 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +SAT: a jabber client +Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + + +from logging import debug, info, warning, error +from twisted.enterprise import adbapi +from twisted.internet import defer +import os.path + +class SqliteStorage(): + """This class manage storage with Sqlite database""" + + + def __init__(self, db_filename): + """Connect to the given database + @param db_filename: full path to the Sqlite database""" + self.initialized = defer.Deferred() #triggered when memory is fully initialised and ready + init_defers = [] #list of deferred we have to wait to before initialisation is complete + self.profiles={} #we keep cache for the profiles (key: profile name, value: profile id) + + info(_("Connecting database")) + new_base = not os.path.exists(db_filename) #do we have to create the database ? + self.dbpool = adbapi.ConnectionPool("sqlite3", db_filename, check_same_thread=False) + init_defers.append(self.dbpool.runOperation("PRAGMA foreign_keys = ON").addErrback(lambda x: error(_("Can't activate foreign keys")))) + if new_base: + info(_("The database is new, creating the tables")) + database_creation = [ + "CREATE TABLE profiles (id INTEGER PRIMARY KEY ASC, name TEXT, UNIQUE (name))", + "CREATE TABLE historic (id INTEGER PRIMARY KEY ASC, profile_id INTEGER, source TEXT, dest TEXT, source_res TEXT, dest_res TEXT, timestamp DATETIME, message TEXT, FOREIGN KEY(profile_id) REFERENCES profiles(id))", + "CREATE TABLE param_gen (category TEXT, name TEXT, value TEXT, PRIMARY KEY (category,name))", + "CREATE TABLE param_ind (category TEXT, name TEXT, profile_id INTEGER, value TEXT, PRIMARY KEY (category,name,profile_id), FOREIGN KEY(profile_id) REFERENCES profiles(id))"] + for op in database_creation: + d = self.dbpool.runOperation(op) + d.addErrback(lambda x: error(_("Error while creating tables in database [QUERY: %s]") % op )) + init_defers.append(d) + + def fillProfileCache(ignore): + d = self.dbpool.runQuery("SELECT name,id FROM profiles").addCallback(self._profilesCache) + d.chainDeferred(self.initialized) + + defer.DeferredList(init_defers).addCallback(fillProfileCache) + + #Profiles + def _profilesCache(self, profiles_result): + """Fill the profiles cache + @param profiles_result: result of the sql profiles query""" + for profile in profiles_result: + name, id = profile + self.profiles[name] = id + + def getProfilesList(self): + """"Return list of all registered profiles""" + return self.profiles.keys() + + def hasProfile(self, profile_name): + """return True if profile_name exists + @param profile_name: name of the profile to check""" + return self.profiles.has_key(profile_name) + + def createProfile(self, name): + """Create a new profile + @param name: name of the profile + @return: deferred triggered once profile is actually created""" + def getProfileId(ignore): + return self.dbpool.runQuery("SELECT (id) FROM profiles WHERE name = ?", (name,)) + + def profile_created(profile_id): + _id = profile_id[0][0] + self.profiles[name] = _id #we synchronise the cache + + d = self.dbpool.runQuery("INSERT INTO profiles(name) VALUES (?)", (name,)) + d.addCallback(getProfileId) + d.addCallback(profile_created) + d.addErrback(lambda ignore: error(_("Can't create profile %(name)s" % {"name":name}))) + return d + + #Params + def loadGenParams(self, params_gen): + """Load general parameters + @param params_gen: dictionary to fill + @return: deferred""" + def fillParams(result): + params_gen[(category, name)] = value + debug(_("loading general parameters from database")) + return self.dbpool.runQuery("SELECT category,name,value FROM param_gen").addCallback(fillParams) + + def loadIndParams(self, params_ind, profile): + """Load general parameters + @param params_ind: dictionary to fill + @param profile: a profile which *must* exist + @return: deferred""" + def fillParams(result): + params_ind[profile][(category, name)] = value + debug(_("loading individual parameters from database")) + d = self.dbpool.runQuery("SELECT category,name,value FROM param_gen WHERE profile_id=?", self.profiles[profile]) + d.addCallback(fillParams) + return d + + def setGenParam(self, category, name, value): + """Save the general parameters in database + @param category: category of the parameter + @param name: name of the parameter + @param value: value to set + @return: deferred""" + d = self.dbpool.runQuery("REPLACE INTO param_gen(category,name,value) VALUES (?,?,?)", (category, name, value)) + d.addErrback(lambda ignore: error(_("Can't set general parameter (%(category)s/%(name)s) in database" % {"category":category, "name":name}))) + return d + + def setIndParam(self, category, name, value, profile): + """Save the general parameters in database + @param category: category of the parameter + @param name: name of the parameter + @param value: value to set + @param profile: a profile which *must* exist + @return: deferred""" + d = self.dbpool.runQuery("REPLACE INTO param_ind(category,name,profile_id,value) VALUES (?,?,?,?)", (category, name, self.profiles[profile], value)) + d.addErrback(lambda ignore: error(_("Can't set individual parameter (%(category)s/%(name)s) for [%(profile)s] in database" % {"category":category, "name":name, "profile":profile}))) + return d