[PATCH 3/9] Re: Experimental LocalStatus stored in SQLite database
Nicolas Sebrecht
nicolas.s-dev at laposte.net
Wed Apr 27 18:13:08 BST 2011
On Tue, Apr 26, 2011 at 12:31:34PM +0200, Sebastian Spaeth wrote:
>
> Based on patches by Stewart Smith, updated by Rob Browning.
> This adds the file without using it yet.
>
> Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
> ---
> offlineimap/folder/LocalStatusSQLite.py | 202 +++++++++++++++++++++++++++++++
> 1 files changed, 202 insertions(+), 0 deletions(-)
> create mode 100644 offlineimap/folder/LocalStatusSQLite.py
>
> diff --git a/offlineimap/folder/LocalStatusSQLite.py b/offlineimap/folder/LocalStatusSQLite.py
> new file mode 100644
> index 0000000..974baf4
> --- /dev/null
> +++ b/offlineimap/folder/LocalStatusSQLite.py
> @@ -0,0 +1,202 @@
> +# Local status cache virtual folder: SQLite backend
> +# Copyright (C) 2009-2011 Stewart Smith and contributors
> +#
> +# 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 2 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, write to the Free Software
> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> +
> +from Base import BaseFolder
> +import os, threading
Don't we want PEP8 (one import per line)? I remember you sending patches
like this. :-)
> +
Why a blank line?
> +from pysqlite2 import dbapi2 as sqlite
> +
> +magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
> +newmagicline = "OFFLINEIMAP LocalStatus NOW IN SQLITE, DO NOT MODIFY"
> +
> +class LocalStatusFolder(BaseFolder):
> + """LocalStatus backend implemented with an SQLite database"""
> + def __deinit__(self):
> + self.save()
> + self.cursor.close()
> + self.connection.close()
> +
> + def __init__(self, root, name, repository, accountname, config):
> + self.name = name
> + self.root = root
> + self.sep = '.'
> + self.config = config
> + self.dofsync = config.getdefaultboolean("general", "fsync", True)
> + self.filename = repository.getfolderfilename(name)
> + self.messagelist = {}
> + self.repository = repository
> + self.savelock = threading.Lock()
> + self.doautosave = 1
> + self.accountname = accountname
> + BaseFolder.__init__(self)
> + self.dbfilename = self.filename + '.sqlite'
Is it the right place for this statement? No newline before?
> +
> + # MIGRATE
I don't think we want such migration plans here. Handling database
format here could end with lot of migration code we don't usually care
about.
I think migration code should be done here _against a "TARGET_FORMAT"_.
Migration processes to go to this format would run all the missing
migration procedures.
Say we're at v6.3.3:1 (:1 for the database format release). Then, comes
v6.4.0:2 and later v6.5.0:3... Yeah, you got my point: what shoud we do
for people going from :1 to :3? And we will get things worse than that
having SQL optionnal at the Account level.
Migrate from LocalStatus to LocalStatusSQLite _IS_ a migration like
above. A bit particular due to the creation of the database but it's
really the same.
IOW, we need something a bit more advanced NOW to force further updates
the right way.
> + if os.path.exists(self.filename):
> + self.connection = sqlite.connect(self.dbfilename)
> + self.cursor = self.connection.cursor()
> + self.cursor.execute('CREATE TABLE status (id INTEGER PRIMARY KEY, flags VARCHAR(50))')
> + if self.isnewfolder():
> + self.messagelist = {}
> + return
Indentation looks ugly.
> + file = open(self.filename, "rt")
> + self.messagelist = {}
Repeated statement?
> + line = file.readline().strip()
> + assert(line == magicline)
I would add a comment here or implement a dummy (no-op) migration
process depending on the migration implementation.
> + for line in file.xreadlines():
> + line = line.strip()
> + uid, flags = line.split(':')
> + uid = long(uid)
> + flags = [x for x in flags]
> + flags.sort()
> + flags = ''.join(flags)
> + self.cursor.execute('INSERT INTO status (id,flags) VALUES (?,?)',
> + (uid,flags))
> + file.close()
Indentation mistakes?
> + self.connection.commit()
> + os.rename(self.filename, self.filename + ".old")
> + self.cursor.close()
> + self.connection.close()
> +
> + # create new
Notice: a creation is a migration. :-)
> + if not os.path.exists(self.dbfilename):
> + self.connection = sqlite.connect(self.dbfilename)
> + self.cursor = self.connection.cursor()
> + self.cursor.execute('CREATE TABLE status (id INTEGER PRIMARY KEY, flags VARCHAR(50))')
> + else:
> + self.connection = sqlite.connect(self.dbfilename)
> + self.cursor = self.connection.cursor()
--
Nicolas Sebrecht
More information about the OfflineIMAP-project
mailing list