"""Module implementing a Postgresql based repository for cfvers"""
# Copyright 2003-2005 Iustin Pop
#
# This file is part of cfvers.
#
# cfvers 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.
#
# cfvers 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 cfvers; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# $Id: r_postgresql.py 218 2005-10-30 09:26:23Z iusty $
import psycopg2
import cfvers.repository.sql
class RPostgresql(cfvers.repository.sql.RSql):
def __init__(self, create=False, cnxargs=None, createopts=None):
self._quote = self._quote_format
self.conn = psycopg2.connect(cnxargs)
self.conn.set_isolation_level(1)
self.backend = 'postgresql'
self.cnxargs = cnxargs
if create:
self._create(createopts=createopts)
self._check_schema(self.conn.cursor())
return
def _init_schema(self, cursor):
cursor.execute("set client_min_messages to 'warning'")
super(RPostgresql, self)._init_schema(cursor)
cursor.execute("ALTER TABLE config SET WITHOUT OIDS")
cursor.execute("ALTER TABLE areas SET WITHOUT OIDS")
cursor.execute("CREATE SEQUENCE items_id_seq")
cursor.execute("ALTER TABLE items SET WITHOUT OIDS")
cursor.execute("ALTER TABLE items ALTER COLUMN id SET DEFAULT nextval('items_id_seq')")
cursor.execute("ALTER TABLE items ADD constraint items_area_fk FOREIGN KEY (area) REFERENCES areas(name) ON UPDATE CASCADE")
cursor.execute("ALTER TABLE entries SET WITHOUT OIDS")
cursor.execute("ALTER TABLE entries ADD CONSTRAINT entries_item_fk FOREIGN KEY (item) REFERENCES items(id)")
cursor.execute("ALTER TABLE revisions ADD CONSTRAINT revisions_area_fk FOREIGN KEY (area) REFERENCES areas(name) ON UPDATE CASCADE")
cursor.execute("ALTER TABLE revisions SET WITHOUT OIDS")
return
def _delete_schema(self, cursor):
super(RPostgresql, self)._delete_schema(cursor)
self._try_stm(cursor, "DROP SEQUENCE items_id_seq")
return
def TimestampFromMx(mxtimestamp):
return mxtimestamp
TimestampFromMx = staticmethod(TimestampFromMx)
def _encode_binary(value):
if not isinstance(value, str):
raise ProgrammingException("Invalid type passed to _encode_binary: %s" % type(value))
return psycopg2.Binary(value)
_encode_binary = staticmethod(_encode_binary)
def _decode_binary(value):
return str(value)
_decode_binary = staticmethod(_decode_binary)
def putRevision(self, r):
"""Adds a Revision to the database and fills its revno
It is important to note that only this function can return a
valid new revision number. Until stored in the repository, the
new revision number cannot be safely determined.
"""
cursor = self.conn.cursor()
# Lock the areas row in order that the next query performs correctly
cursor.execute("select * from areas where name = %s for update", (r.area,))
cursor.execute("insert into revisions (area, revno, logmsg, ctime, uid, gid, uname, gname, commiter, server) values (%s, (select coalesce(max(revno), 0)+1 from revisions where area = %s), %s, %s, %s, %s, %s, %s, %s, %s)",
(r.area, r.area, r.logmsg, self.TimestampFromMx(r.ctime),
r.uid, r.gid, r.uname, r.gname,
r.commiter, r.server))
cursor.execute("select max(revno) from revisions where area = %s", (r.area,))
row = cursor.fetchone()
r.revno = row[0]
return r
def quotestr(value):
return psycopg2.QuotedString(value)
quotestr = staticmethod(quotestr)
syntax highlighted by Code2HTML, v. 0.9.1