[Zope-Checkins] CVS: Products/AdaptableStorage/gateway_sql - SQLUserList.py:1.1 public.py:1.4

Shane Hathaway shane@zope.com
Tue, 7 Jan 2003 00:08:09 -0500


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

Modified Files:
	public.py 
Added Files:
	SQLUserList.py 
Log Message:
- Added SQLUserList.  All tests pass again.

- Refactored Zope 2 tests to share a common implementation,
Zope2TestBase.


=== Added File Products/AdaptableStorage/gateway_sql/SQLUserList.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: SQLUserList.py,v 1.1 2003/01/07 05:07:36 shane Exp $
"""

from SQLGatewayBase import SQLGatewayBase
from mapper_public import IGateway, RowSequenceSchema


class SQLUserList (SQLGatewayBase):
    """Stores and retrieves all users for a folder at once."""

    __implements__ = IGateway

    schema = RowSequenceSchema()
    schema.addField('id', 'string', 1)
    schema.addField('password', 'string')
    schema.addField('roles', 'string:list')
    schema.addField('domains', 'string:list')

    table_base_name = 'users'

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

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

    create_roles_sql = '''CREATE TABLE %(roles_table)s (
    key int,
    id character varying(255),
    role character varying(255)
    )'''

    create_domains_sql = '''CREATE TABLE %(domains_table)s (
    key int,
    id character varying(255),
    domain character varying(255)
    )'''

    read_sql = '''SELECT id, password FROM %(table)s
    WHERE key = %(key)s'''

    read_roles_sql = '''SELECT id, role FROM %(roles_table)s
    WHERE key = %(key)s'''

    read_domains_sql = '''SELECT id, domain FROM %(domains_table)s
    WHERE key = %(key)s'''

    update_sql = '''UPDATE %(table)s
    SET password = %(password)s
    WHERE key = %(key)s AND id = %(id)s'''

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

    delete_sql = '''DELETE FROM %(table)s
    WHERE key = %(key)s and id = %(id)s'''

    delete_roles_sql = '''DELETE FROM %(roles_table)s
    WHERE key = %(key)s and id = %(id)s'''

    delete_domains_sql = '''DELETE FROM %(domains_table)s
    WHERE key = %(key)s and id = %(id)s'''

    insert_role_sql = '''INSERT INTO %(roles_table)s
    (key, id, role)
    VALUES (%(key)s, %(id)s, %(role)s)'''

    insert_domain_sql = '''INSERT INTO %(domains_table)s
    (key, id, domain)
    VALUES (%(key)s, %(id)s, %(domain)s)'''

    clear_roles_sql = 'DELETE FROM %(roles_table)s'

    clear_domains_sql = 'DELETE FROM %(domains_table)s'


    def __init__(self, conn):
        self.roles_table = conn.prefix + '_user_roles'
        self.domains_table = conn.prefix + '_user_domains'
        SQLGatewayBase.__init__(self, conn)

    def setupTables(self):
        conn = self.conn
        try:
            self.execute(self.checkexist_sql)
        except conn.error:
            conn.db.rollback()
            self.execute(self.create_sql)
            self.execute(self.create_roles_sql)
            self.execute(self.create_domains_sql)
            conn.db.commit()

    def execute(self, text, *args, **kw):
        text = text.replace('%(table)s', self.table)
        text = text.replace('%(roles_table)s', self.roles_table)
        text = text.replace('%(domains_table)s', self.domains_table)
        return self.conn.execute(text, *args, **kw)

    def clear(self):
        self.execute(self.clear_sql)
        self.execute(self.clear_roles_sql)
        self.execute(self.clear_domains_sql)

    def getSchema(self):
        return self.schema


    def load(self, event):
        key = event.getKeychain()[-1]
        rows = self.execute(self.read_sql, 1, key=key)
        data = {}
        for id, password in rows:
            data[id] = (password, [], [])
        rows = self.execute(self.read_roles_sql, 1, key=key)
        for id, role in rows:
            row = data.get(id)
            if row is not None:
                row[1].append(role)
        rows = self.execute(self.read_domains_sql, 1, key=key)
        for id, domain in rows:
            row = data.get(id)
            if row is not None:
                row[2].append(domain)
        records = []
        for id, (password, roles, domains) in data.items():
            records.append((id, password, tuple(roles), tuple(domains)))
        records.sort()
        return records, tuple(records)


    def store(self, event, state):
        keychain = event.getKeychain()
        keychain1 = keychain[:-1]
        key = int(keychain[-1])
        old_rows, old_serial = self.load(event)
        new_dict = {}
        for rec in state:
            new_dict[rec[0]] = rec
        old_dict = {}
        for rec in old_rows:
            old_dict[rec[0]] = rec

        # Compare / remove rows.
        for old_row in old_rows:
            id = old_row[0]
            new_row = new_dict.get(id)
            if new_row is None:
                # Remove this row.
                self.execute(self.delete_sql, key=key, id=id)
                self.execute(self.delete_roles_sql, key=key, id=id)
                self.execute(self.delete_domains_sql, key=key, id=id)
            elif new_row == old_row:
                # Don't need to update this row.
                del new_rows[id]

        # Insert / update rows.
        for new_row in new_dict.values():
            id, password, roles, domains = new_row
            old_row = old_dict.get(id)
            if old_row is not None:
                old_id, old_password, old_roles, old_domains = old_row
                if old_password != password:
                    # Update the password.
                    self.execute(self.update_sql, key=key, id=id,
                                 password=password)
            else:
                # Insert a new record.
                self.execute(self.insert_sql, key=key, id=id,
                             password=password)
                old_roles = ()
                old_domains = ()

            # Update the role list.
            if tuple(roles) != tuple(old_roles):
                self.execute(self.delete_roles_sql, key=key, id=id)
                for role in roles:
                    assert role
                    self.execute(self.insert_role_sql, key=key, id=id,
                                 role=role)

            # Update the domain list.
            if tuple(domains) != tuple(old_domains):
                self.execute(self.delete_domains_sql, key=key, id=id)
                for domain in domains:
                    assert domain
                    self.execute(self.insert_domain_sql, key=key, id=id,
                                 domain=domain)
                
        state = list(state)
        state.sort()
        return tuple(state)



=== Products/AdaptableStorage/gateway_sql/public.py 1.3 => 1.4 ===
--- Products/AdaptableStorage/gateway_sql/public.py:1.3	Fri Jan  3 17:04:19 2003
+++ Products/AdaptableStorage/gateway_sql/public.py	Tue Jan  7 00:07:36 2003
@@ -25,3 +25,4 @@
 from SQLObjectData import SQLObjectData
 from SQLProperties import SQLProperties
 from SQLRemainder import SQLRemainder
+from SQLUserList import SQLUserList