[Zope-CVS] CVS: Products/AdaptableStorage/gateway_sql - PsycopgConnection.py:1.1 SQLClassification.py:1.1 SQLFolderItems.py:1.1 SQLItemId.py:1.1 SQLKeychainGenerator.py:1.1 SQLRemainder.py:1.1 public.py:1.1 serial_public.py:1.1

Shane Hathaway shane@zope.com
Tue, 10 Dec 2002 15:37:53 -0500


Update of /cvs-repository/Products/AdaptableStorage/gateway_sql
In directory cvs.zope.org:/tmp/cvs-serv10311/gateway_sql

Added Files:
	PsycopgConnection.py SQLClassification.py SQLFolderItems.py 
	SQLItemId.py SQLKeychainGenerator.py SQLRemainder.py public.py 
	serial_public.py 
Log Message:
Checkpoint: storage to a Postgres database.  Not working yet.


=== Added File Products/AdaptableStorage/gateway_sql/PsycopgConnection.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Psycopg connectivity

$Id: PsycopgConnection.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

import psycopg


class PsycopgConnection:

    _final = 0

    def __init__(self, params='', prefix='zodb'):
        self.db = psycopg.connect(params)
        self.prefix = prefix
        self.error = psycopg.DatabaseError

    def execute(self, text, fetch=0, cursor=None, **kw):
        created = 0
        if cursor is None:
            created = 1
            cursor = self.db.cursor()
        try:
            cursor.execute(text, kw)
            if fetch:
                return cursor.fetchall()
            else:
                return None
        finally:
            if created:
                cursor.close()

    def begin(self):
        pass

    def vote(self):
        self._final = 1

    def reset(self):
        self._final = 0

    def abort(self):
        self.reset()

    def finish(self):
        if self._final:
            try:
                self.db.commit()
            finally:
                self.reset()



=== Added File Products/AdaptableStorage/gateway_sql/SQLClassification.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""SQL classification gateway

$Id: SQLClassification.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from serial_public import IGateway, FieldSchema

checkexist_sql = '''SELECT key FROM %(table)s LIMIT 1'''

create_sql = '''CREATE TABLE %(table)s (
  key int PRIMARY KEY,
  meta_type character varying(255),
  class_name character varying(255)  
)'''

read_sql = '''SELECT meta_type, class_name from %(table)s
  WHERE key = %(key)s'''

update_sql = '''UPDATE %(table)s
  SET meta_type=%(meta_type)s, class_name=%(class_name)s
  WHERE key = %(key)s'''

insert_sql = '''INSERT INTO %(table)s
  (key, meta_type, class_name)
  VALUES (%(key)s, %(meta_type)s, %(class_name)s)'''

drop_sql = '''DROP TABLE %(table)s'''


class SQLClassification:

    __implements__ = IGateway

    schema = FieldSchema('classification', 'classification')

    def __init__(self, conn):
        self.conn = conn
        self.table = conn.prefix + '_classification'
        try:
            self.execute(checkexist_sql)
        except conn.error:
            self.execute(create_sql)

    def execute(self, *args, **kw):
        kw['table'] = self.table
        return self.conn.execute(*args, **kw)

    def drop(self):
        self.execute(drop_sql)

    def load(self, event):
        key = int(event.getKeychain()[-1])
        items = self.execute(read_sql, 1, key=key)
        classification = {}
        if items:
            rec = items[0]
            if rec[0]:
                classification['meta_type'] = rec[0]
            if rec[1]:
                classification['class_name'] = rec[1]
        else:
            rec = ()
        return classification, rec

    def store(self, event, classification):
        key = int(event.getKeychain()[-1])
        items = self.execute(read_sql, 1, key=key)
        mt = classification.get('meta_type', '')
        cn = classification.get('class_name', '')
        kw = {'key': key, 'meta_type': mt, 'class_name': cn}
        if items:
            # update.
            self.execute(update_sql, **kw)
        else:
            # insert.
            self.execute(insert_sql, **kw)
        return (mt, cn)



=== Added File Products/AdaptableStorage/gateway_sql/SQLFolderItems.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""SQL folder items gateway

$Id: SQLFolderItems.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from serial_public import IGateway, RowSequenceSchema


checkexist_sql = '''SELECT key FROM %(table)s LIMIT 1'''

create_sql = '''CREATE TABLE %(table)s (
  key int,
  name character varying(255),
  child_key int
)'''

read_sql = '''SELECT name, child_key from %(table)s
  WHERE key = %(key)s'''

update_sql = '''UPDATE %(table)s
  SET child_key=%(child_key)s
  WHERE key = %(key)s and name = %(name)s'''

insert_sql = '''INSERT INTO %(table)s
  (key, name, child_key)
  VALUES (%(key)s, %(name)s, %(child_key)s)'''

drop_sql = '''DROP TABLE %(table)s'''


class SQLFolderItems:

    __implements__ = IGateway

    schema = RowSequenceSchema()
    schema.addField('id', 'string', 1)
    schema.addField('keychain', 'keychain')

    def __init__(self, conn):
        self.conn = conn
        self.table = conn.prefix + '_folder_items'
        try:
            self.execute(checkexist_sql)
        except conn.error:
            self.execute(create_sql)

    def execute(self, *args, **kw):
        kw['table'] = self.table
        return self.conn.execute(*args, **kw)

    def drop(self):
        self.execute(drop_sql)

    def load(self, event):
        key = int(event.getKeychain()[-1])
        items = self.execute(read_sql, 1, key=key)
        items.sort()
        res = [(rec[0], key + (rec[1],)) for rec in res]
        return res, tuple(res)

    def store(self, event, state):
        keychain = event.getKeychain()
        keychain1 = keychain[:-1]
        key = int(keychain[-1])
        items = self.execute(read_sql, 1, key=key)
        dict = {}
        for name, child_key in items:
            dict[name] = child_key
        state = list(state)
        state.sort()
        for name, child_keychain in state:
            if child_keychain[:-1] != keychain1:
                raise RuntimeError(
                    "SQLFolderItems cannot store cross-domain references")
            child_key = int(child_keychain[-1])
            kw = {'key': key, 'name': name, 'child_key': child_key}
            if dict.has_key(name):
                if dict[name] != child_key:
                    self.execute(update_sql, **kw)
            else:
                self.execute(insert_sql, **kw)
        return tuple(state)



=== Added File Products/AdaptableStorage/gateway_sql/SQLItemId.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""SQL item ID gateway.  Piggybacks SQLFolderItems and makes the assumption
that the item is stored in only one place.

$Id: SQLItemId.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from serial_public import IGateway, FieldSchema


read_sql = '''SELECT name from %(table)s
  WHERE child_key = %(child_key)s'''


class SQLItemId:

    __implements__ = IGateway

    schema = FieldSchema('id', 'string')

    def __init__(self, conn):
        self.conn = conn
        self.table = conn.prefix + '_folder_items'

    def execute(self, *args, **kw):
        kw['table'] = self.table
        return self.conn.execute(*args, **kw)

    def load(self, event):
        key = int(event.getKeychain()[-1])
        rows = self.execute(read_sql, 1, child_key=key)
        assert len(rows) >= 1
        name = rows[0][0]
        return name, name

    def store(self, event, state):
        # Assume that SQLFolderItems stored or will store the name.
        return state


=== Added File Products/AdaptableStorage/gateway_sql/SQLKeychainGenerator.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""SQL keychain generator

$Id: SQLKeychainGenerator.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from serial_public import IKeychainGenerator


checkexist_sql = '''SELECT last_value FROM %(sequence)s'''

create_sql = '''CREATE SEQUENCE %(sequence)s'''

read_sql = """SELECT nextval('%(sequence)s')"""

drop_sql = '''DROP SEQUENCE %(sequence)s'''


class SQLKeychainGenerator:

    __implements__ = IKeychainGenerator

    def __init__(self, conn):
        self.conn = conn
        self.sequence = conn.prefix + '_key_seq'
        try:
            self.execute(checkexist_sql)
        except conn.error:
            self.execute(create_sql)

    def execute(self, *args, **kw):
        kw['sequence'] = self.sequence
        return self.conn.execute(*args, **kw)

    def makeKeychain(self, event, name, stored):
        if not stored:
            raise RuntimeError(
                'Keychains generated by SQLKeychain must be stored')
        n = self.execute(read_sql, 1)[0]
        return event.getKeychain()[:-1] + (str(n),)

    def drop(self):
        self.execute(drop_sql)



=== Added File Products/AdaptableStorage/gateway_sql/SQLRemainder.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""SQL remainder pickle gateway

$Id: SQLRemainder.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from serial_public import IGateway, FieldSchema


checkexist_sql = '''SELECT key FROM %(table)s LIMIT 1'''

create_sql = '''CREATE TABLE %(table)s (
  key int PRIMARY_KEY,
  pickle bytea
)'''

read_sql = '''SELECT pickle from %(table)s
  WHERE key = %(key)s'''

update_sql = '''UPDATE %(table)s
  SET pickle=%(pickle)s
  WHERE key = %(key)s'''

insert_sql = '''INSERT INTO %(table)s
  (key, pickle)
  VALUES (%(key)s, %(pickle)s)'''

drop_sql = '''DROP TABLE %(table)s'''


class SQLRemainder:

    __implements__ = IGateway

    schema = FieldSchema('data', 'string')

    def __init__(self, conn):
        self.conn = conn
        self.table = conn.prefix + '_remainder'
        try:
            self.execute(checkexist_sql)
        except conn.error:
            self.execute(create_sql)

    def execute(self, *args, **kw):
        kw['table'] = self.table
        return self.conn.execute(*args, **kw)

    def drop(self):
        self.execute(drop_sql)

    def load(self, event):
        key = int(event.getKeychain()[-1])
        items = self.execute(read_sql, 1, key=key)
        if items:
            state = items[0][0]
        else:
            state = ''
        return state, state

    def store(self, event, state):
        key = int(event.getKeychain()[-1])
        items = self.execute(read_sql, 1, key=key)
        kw = {'key': key, 'pickle': state}
        if items:
            # update.
            self.execute(update_sql, **kw)
        else:
            # insert.
            self.execute(insert_sql, **kw)
        return state



=== Added File Products/AdaptableStorage/gateway_sql/public.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""gateway_sql public names

$Id: public.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from PsycopgConnection import PsycopgConnection
from SQLClassification import SQLClassification
from SQLFolderItems import SQLFolderItems
from SQLItemId import SQLItemId
from SQLKeychainGenerator import SQLKeychainGenerator
from SQLRemainder import SQLRemainder



=== Added File Products/AdaptableStorage/gateway_sql/serial_public.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Import of the public classes and interfaces from the serial package.

$Id: serial_public.py,v 1.1 2002/12/10 20:37:52 shane Exp $
"""

from Products.AdaptableStorage.serial.public import *