[Zope-CVS] CVS: Products/Ape/lib/apelib/sql - table.py:1.1.2.1
classification.py:1.8.2.1 dbapi.py:1.11.2.1
interfaces.py:1.4.2.1 oidgen.py:1.5.2.1
properties.py:1.11.2.1 security.py:1.8.2.1
sqlbase.py:1.13.2.1 structure.py:1.11.2.1
Shane Hathaway
shane at zope.com
Tue Jul 20 02:12:43 EDT 2004
Update of /cvs-repository/Products/Ape/lib/apelib/sql
In directory cvs.zope.org:/tmp/cvs-serv3989
Modified Files:
Tag: sql-types-branch
classification.py dbapi.py interfaces.py oidgen.py
properties.py security.py sqlbase.py structure.py
Added Files:
Tag: sql-types-branch
table.py
Log Message:
Created a branch for better mapping Python types to SQL databases.
Some databases do not automatically convert types (such as strings to
integers). This branch seeks to restructure apelib.sql in such a way
that type conversion can be done in Python.
=== Added File Products/Ape/lib/apelib/sql/table.py ===
##############################################################################
#
# Copyright (c) 2004 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 implementation of IRDBMSTable.
$Id: table.py,v 1.1.2.1 2004/07/20 06:12:43 shane Exp $
"""
from apelib.sql.interfaces import IRDBMSTable, IRDBMSColumn
class SQLTable:
"""Talks to a table via SQL."""
__implements__ = IRDBMSTable
def __init__(self, connection, name, columns):
self.name = name
self.execute = connection.execute
for key, value in columns:
assert IRDMSColumn.isImplementedBy(value)
self.columns = dict(columns)
self.column_order = [key for (key, value) in columns]
def generate_conditions(self, col_names):
clauses = [
"%s = :%s" % (self.columns[c].name, c) for c in col_names]
return ' AND '.join(clauses)
def generate_select(self, filter_col_names, result_col_names):
result_names = [self.columns[col].name for col in col_names]
sql = 'SELECT %s FROM %s' % (', '.join(result_names), self.name)
where = self.generate_conditions(filter_col_names)
if where:
sql += ' WHERE %s' % where
return sql
def generate_insert(self, col_names):
names = [self.columns[c].name for c in col_names]
colfmts = [':%s' % c for c in col_names]
return 'INSERT INTO %s (%s) VALUES (%s)' % (
self.name, ', '.join(names), ', '.join(colfmts))
def generate_update(self, key_col_names, other_col_names):
where = self.generate_conditions(key_col_names)
to_set = [
("%s = :%s" % (self.columns[c].name, c))
for c in other_col_names]
return 'UPDATE %s SET %s WHERE %s' % (
self.name, ', '.join(to_set), where)
def generate_delete(self, col_names):
where = self.generate_conditions(col_names)
sql = 'DELETE FROM %s' % self.name
if where:
sql += ' WHERE %s' % where
return sql
def prepare_for_db(self, col_names, data, oid=None):
"""Prepares one row for writing to the database."""
res = {}
for n in range(len(col_names)):
c = col_names[n]
res[c] = self.columns[c].to_db(data[n])
if oid is not None:
res['oid'] = self.columns[c].to_db(oid)
return res
#
# IRDBMSTable implementation.
#
def select(self, result_col_names, **filter):
"""Selects rows from a table and returns column values for those rows.
"""
sql = self.generate_select(filter.keys(), result_col_names)
f = {}
for col_name, value in filter.items():
f[col_name] = self.columns[col_name].to_db(value)
db_res = self.execute(sql, f, fetch=1)
# Convert the result to standard types.
res = []
from_db = []
for n in range(len(result_col_names)):
from_db.append((n, self.columns[result_col_names[n]].from_db))
for row in db_res:
r = [from_db(row[n]) for (n, column) in dbcols]
res.append(tuple(r))
return res
def insert(self, col_names, row):
"""Inserts one row in the table.
"""
kw = self.prepare_for_db(col_names, row)
sql = self.generate_insert(col_names)
self.execute(sql, kw)
def set_one(self, oid, col_names, row, is_new):
"""Sets one row in a table.
Requires the table to have only one value for each oid.
Executes either an update or insert operation, depending on
the is_new argument and configured policies.
"""
kw = self.prepare_for_db(col_names, row, oid)
if is_new:
sql = self.generate_insert(('oid',) + tuple(col_names))
self.execute(sql, kw)
else:
sql = self.generate_update(('oid',), col_names)
self.execute(sql, kw)
def set_many(self, oid, key_col_names, other_col_names, rows):
"""Sets multiple rows in a table.
'rows' is a sequence of tuples containing values for the
key_columns as well as the other_columns.
Either deletes all rows for an oid and inserts new rows, or
examines the current state of the database and modifies it in
pieces.
"""
combo = tuple(key_col_names) + tuple(other_col_names)
if not key_col_names:
# Don't compare rows. Just delete and insert.
sql = self.generate_delete(('oid',))
self.execute(sql, {'oid': oid})
for row in rows:
sql = self.generate_insert(('oid',) + combo)
kw = self.prepare_for_db(combo, row, oid)
self.execute(sql, kw)
return
# Edit the table.
exist_rows = self.select(combo, oid=oid)
count = len(key_col_names)
existing = {}
for record in exist_rows:
key = tuple(record[:count])
value = tuple(record[count:])
existing[key] = value
now = {}
for record in rows:
key = tuple(record[:count])
value = tuple(record[count:])
now[key] = value
# Delete and update rows.
for key, value in existing.items():
if not now.has_key(key):
# Delete this row.
sql = self.generate_delete(('oid',) + tuple(key_col_names))
kw = self.prepare_for_db(key_col_names, key, oid)
self.execute(sql, kw)
elif now[key] != value:
# Update this row.
#print 'DIFFERENT:', now[key], value
sql = self.generate_update(
('oid',) + tuple(key_col_names), other_col_names)
kw = self.prepare_for_db(combo, key + now[key], oid)
self.execute(sql, kw)
for key, value in now.items():
if not existing.has_key(key):
# Insert this row.
sql = self.generate_insert(('oid',) + combo)
kw = self.prepare_for_db(combo, key + value, oid)
self.execute(sql, kw)
return
def delete_rows(self, **filter):
"""Deletes rows from the table.
"""
sql = self.generate_delete(filter.keys())
self.execute(sql, filter)
def create(self):
"""Creates the table.
"""
pkeys = []
for c in self.column_order:
col = self.columns[c]
constraints = ''
if unique:
constraints = ' NOT NULL'
pkeys.append(col.name)
col_decls.append(
"%s %s%s" % (col.name, col.type, constraints))
if pkeys:
col_decls.append('PRIMARY KEY (%s)' % ', '.join(pkeys))
sql = "CREATE TABLE %s (%s)" % (self.name, ', '.join(col_decls))
self.execute(sql)
def drop(self):
"""Drops the table.
"""
sql = "DROP TABLE %s" % self.name
self.execute(sql)
=== Products/Ape/lib/apelib/sql/classification.py 1.8 => 1.8.2.1 ===
--- Products/Ape/lib/apelib/sql/classification.py:1.8 Sat Mar 20 01:34:23 2004
+++ Products/Ape/lib/apelib/sql/classification.py Tue Jul 20 02:12:43 2004
@@ -16,7 +16,7 @@
$Id$
"""
-from apelib.core.schemas import FieldSchema
+from apelib.core.schemas import FieldSchema, Column
from apelib.core.interfaces import OIDConflictError
from sqlbase import SQLGatewayBase
@@ -26,15 +26,15 @@
__implements__ = SQLGatewayBase.__implements__
schema = FieldSchema('classification', 'classification')
- table = 'classification'
- column_defs = (
- ('class_name', 'string', 0),
- ('mapper_name', 'string', 0),
- )
+ table_name = 'classification'
+ columns = [
+ Column('class_name', 'string', 0),
+ Column('mapper_name', 'string', 0),
+ ]
def load(self, event):
- conn = self.get_connection(event)
- rows = conn.select(self.table, self.columns, oid=event.oid)
+ table = self.get_table(event)
+ rows = table.select(self.column_names, oid=event.oid)
classification = {}
if rows:
rec = rows[0]
@@ -47,11 +47,11 @@
return classification, rec
def store(self, event, classification):
- conn = self.get_connection(event)
+ table = self.get_table(event)
row = (classification.get('class_name', ''),
classification.get('mapper_name', ''))
try:
- conn.set_one(self.table, event.oid, self.columns, row, event.is_new)
+ table.set_one(event.oid, self.column_names, row, event.is_new)
except conn.module.IntegrityError:
raise OIDConflictError(event.oid)
return row
=== Products/Ape/lib/apelib/sql/dbapi.py 1.11 => 1.11.2.1 ===
--- Products/Ape/lib/apelib/sql/dbapi.py:1.11 Thu Apr 15 19:15:42 2004
+++ Products/Ape/lib/apelib/sql/dbapi.py Tue Jul 20 02:12:43 2004
@@ -34,10 +34,11 @@
__implements__ = IRDBMSConnection, ITPCConnection
- column_type_translations = {} # { local type name -> db type name }
- column_name_translations = {} # { local col name -> db col name }
+ #column_type_translations = {} # { local type name -> db type name }
+ #column_name_translations = {} # { local col name -> db col name }
module = None
connector = None
+ tables = None
def __init__(self, module_name, connect_expression, prefix=''):
# connect_expression is a Python expression.
@@ -46,165 +47,17 @@
self.connect_expression = connect_expression
self.prefix = prefix
self.connector = None
+ self.tables = {}
self._final = 0
def __repr__(self):
return '<%s(module_name=%s)>' % (
self.__class__.__name__, repr(self.module_name))
- def translate_name(self, column_name):
- """Returns a column name for a variable name.
-
- Defaults to no translation.
- """
- return self.column_name_translations.get(column_name, column_name)
-
- def translate_type(self, column_type):
- """Returns a database type for a variable type.
-
- If the type is unknown, raises KeyError.
- """
- return self.column_type_translations.get(column_type, column_type)
-
- def generate_conditions(self, keys):
- conditions = []
- for key in keys:
- clause = "%s = :%s" % (self.translate_name(key), key)
- conditions.append(clause)
- return ' AND '.join(conditions)
-
- def generate_insert(self, table_name, columns):
- dbcols = [self.translate_name(col) for col in columns]
- colfmts = [':%s' % col for col in columns]
- return 'INSERT INTO %s (%s) VALUES (%s)' % (
- table_name, ', '.join(dbcols), ', '.join(colfmts))
-
- def generate_update(self, table_name, key_columns, other_columns):
- where = self.generate_conditions(key_columns)
- to_set = [
- ("%s = :%s" % (self.translate_name(col), col))
- for col in other_columns]
- return 'UPDATE %s SET %s WHERE %s' % (
- table_name, ', '.join(to_set), where)
-
- def generate_delete(self, table_name, keys):
- where = self.generate_conditions(keys)
- sql = 'DELETE FROM %s' % table_name
- if where:
- sql += ' WHERE %s' % where
- return sql
-
- def make_dict(self, columns, data, oid=None):
- res = {}
- for n in range(len(columns)):
- res[columns[n]] = data[n]
- if oid is not None:
- res['oid'] = oid
- return res
-
#
# IRDBMSConnection implementation.
#
- def select(self, table, result_columns, **filter):
- """Selects rows from a table and returns column values for those rows.
- """
- table_name = self.prefix + table
- dbcols = [self.translate_name(col) for col in result_columns]
- where = self.generate_conditions(filter.keys())
- sql = 'SELECT %s FROM %s' % (', '.join(dbcols), table_name)
- if where:
- sql += ' WHERE %s' % where
- return self.execute(sql, filter, fetch=1)
-
- def insert(self, table, columns, row):
- """Inserts one row in the table.
- """
- table_name = self.prefix + table
- kw = self.make_dict(columns, row)
- sql = self.generate_insert(table_name, columns)
- self.execute(sql, kw)
-
- def set_one(self, table, oid, columns, row, is_new):
- """Sets one row in a table.
-
- Requires the table to have only one value for each oid.
- Executes either an update or insert operation, depending on
- the is_new argument and configured policies.
- """
- table_name = self.prefix + table
- kw = self.make_dict(columns, row, oid)
- if is_new:
- sql = self.generate_insert(table_name, ('oid',) + tuple(columns))
- self.execute(sql, kw)
- else:
- sql = self.generate_update(table_name, ('oid',), columns)
- self.execute(sql, kw)
-
- def set_many(self, table, oid, key_columns, other_columns, rows):
- """Sets multiple rows in a table.
-
- 'rows' is a sequence of tuples containing values for the
- key_columns as well as the other_columns.
-
- Either deletes all rows for an oid and inserts new rows, or
- examines the current state of the database and modifies it in
- pieces.
- """
- table_name = self.prefix + table
- combo = tuple(key_columns) + tuple(other_columns)
- if not key_columns:
- # Don't compare rows. Just delete and insert.
- sql = self.generate_delete(table_name, ('oid',))
- self.execute(sql, {'oid': oid})
- for row in rows:
- sql = self.generate_insert(table_name, ('oid',) + combo)
- kw = self.make_dict(combo, row, oid)
- self.execute(sql, kw)
- return
- # Edit the table.
- exist_rows = self.select(table, combo, oid=oid)
- count = len(key_columns)
- existing = {}
- for record in exist_rows:
- key = tuple(record[:count])
- value = tuple(record[count:])
- existing[key] = value
- now = {}
- for record in rows:
- key = tuple(record[:count])
- value = tuple(record[count:])
- now[key] = value
- # Delete and update rows.
- for key, value in existing.items():
- if not now.has_key(key):
- # Delete this row.
- sql = self.generate_delete(
- table_name, ('oid',) + tuple(key_columns))
- kw = self.make_dict(key_columns, key, oid)
- self.execute(sql, kw)
- elif now[key] != value:
- # Update this row.
- #print 'DIFFERENT:', now[key], value
- sql = self.generate_update(
- table_name, ('oid',) + tuple(key_columns), other_columns)
- kw = self.make_dict(combo, key + now[key], oid)
- self.execute(sql, kw)
- for key, value in now.items():
- if not existing.has_key(key):
- # Insert this row.
- sql = self.generate_insert(table_name, ('oid',) + combo)
- kw = self.make_dict(combo, key + value, oid)
- self.execute(sql, kw)
- return
-
- def delete_from(self, table, **filter):
- """Deletes rows from a table.
- """
- table_name = self.prefix + table
- sql = self.generate_delete(table_name, filter.keys())
- self.execute(sql, filter)
-
def exists(self, name, type_name):
"""Returns true if the specified database object exists.
@@ -216,32 +69,6 @@
"""Returns a list of existing table names.
"""
raise NotImplementedError("Abstract Method")
-
- def create_table(self, table, column_defs):
- """Creates a table.
- """
- table_name = self.prefix + table
- cols = []
- pkeys = []
- for name, typ, unique in column_defs:
- col = self.translate_name(name)
- db_type = self.translate_type(typ)
- constraints = ''
- if unique:
- constraints = ' NOT NULL'
- pkeys.append(col)
- cols.append("%s %s%s" % (col, db_type, constraints))
- if pkeys:
- cols.append('PRIMARY KEY (%s)' % ', '.join(pkeys))
- sql = "CREATE TABLE %s (%s)" % (table_name, ', '.join(cols))
- self.execute(sql)
-
- def drop_table(self, table):
- """Drops a table.
- """
- table_name = self.prefix + table
- sql = "DROP TABLE %s" % table_name
- self.execute(sql)
def create_sequence(self, name, start=1):
"""Creates a sequence.
=== Products/Ape/lib/apelib/sql/interfaces.py 1.4 => 1.4.2.1 ===
--- Products/Ape/lib/apelib/sql/interfaces.py:1.4 Wed Mar 24 22:17:08 2004
+++ Products/Ape/lib/apelib/sql/interfaces.py Tue Jul 20 02:12:43 2004
@@ -18,6 +18,8 @@
from Interface import Interface
from Interface.Attribute import Attribute
+from apelib.core.interfaces import IColumn
+
class IRDBMSConnection (Interface):
"""Interface of basic RDBMS connections.
@@ -30,23 +32,57 @@
connector = Attribute("connector", "The shared DB-API connection")
- def select(table, result_columns, **filter):
- """Selects rows from a table and returns column values for those rows.
+ def exists(name, type_name):
+ """Returns true if the specified database object exists.
+
+ 'name' is the name of the object. 'type_name' is 'table' or
+ 'sequence'.
"""
- def insert(table, columns, row):
- """Inserts one row in a table.
+ def define_table(name, columns):
+ """Creates and returns an IRDBMSTable."""
+
+ def get_table(name):
+ """Returns a previously defined IRDBMSTable."""
+
+ def list_table_names():
+ """Returns a list of existing table names."""
+
+ def create_sequence(name, start=1):
+ """Creates a sequence."""
+
+ def reset_sequence(name, start=1):
+ """Resets a sequence to a starting value."""
+
+ def increment(name):
+ """Increments a sequence and returns the value.
+
+ Whether the value is before or after the increment is not specified.
"""
- def set_one(table, oid, columns, row, is_new):
- """Sets one row in a table.
+
+class IRDBMSTable (Interface):
+ """A table in a database."""
+
+ def exists():
+ """Returns true if this table exists in the database."""
+
+ def select(result_columns, **filter):
+ """Selects rows from a table and returns column values for those rows.
+ """
+
+ def insert(columns, row):
+ """Inserts one row in the table."""
+
+ def set_one(oid, columns, row, is_new):
+ """Sets one row in the table.
Executes either an update or insert operation, depending
on the is_new argument and configured policies.
"""
- def set_many(table, oid, key_columns, other_columns, rows):
- """Sets multiple rows in a table.
+ def set_many(oid, key_columns, other_columns, rows):
+ """Sets multiple rows in the table.
'rows' is a sequence of tuples containing values for the
key_columns as well as the other_columns.
@@ -56,41 +92,22 @@
pieces.
"""
- def delete_from(table, **filter):
- """Deletes rows from a table.
- """
+ def delete_rows(**filter):
+ """Deletes rows from the table."""
- def exists(name, type_name):
- """Returns true if the specified database object exists.
+ def create():
+ """Creates the table."""
- 'name' is the name of the object. 'type_name' is 'table' or
- 'sequence'.
- """
+ def drop():
+ """Drops the table."""
- def list_table_names():
- """Returns a list of existing table names.
- """
- def create_table(name, column_defs):
- """Creates a table.
+class IRDBMSColumn (IColumn):
+ """A column associated with a specific database."""
- column_defs is [(name, type, is_unique)].
- """
+ def to_db(value):
+ """Converts a generic value to a database-specific value."""
- def drop_table(table):
- """Drops a table.
- """
+ def from_db(value):
+ """Converts a database-specific value to a generic value."""
- def create_sequence(name, start=1):
- """Creates a sequence.
- """
-
- def reset_sequence(name, start=1):
- """Resets a sequence to a starting value.
- """
-
- def increment(name):
- """Increments a sequence and returns the value.
-
- Whether the value is before or after the increment is not specified.
- """
=== Products/Ape/lib/apelib/sql/oidgen.py 1.5 => 1.5.2.1 ===
--- Products/Ape/lib/apelib/sql/oidgen.py:1.5 Fri Mar 26 10:52:49 2004
+++ Products/Ape/lib/apelib/sql/oidgen.py Tue Jul 20 02:12:43 2004
@@ -26,13 +26,13 @@
__implements__ = (interfaces.IOIDGenerator,
interfaces.IDatabaseInitializer)
- table = 'oid_seq'
- column_defs = ()
+ table_name = 'oid_seq'
+ columns = []
root_oid = "0"
def init(self, event):
conn = self.get_connection(event)
- if not conn.exists(self.table, 'sequence'):
+ if not conn.exists(self.table_name, 'sequence'):
conn.create_sequence(self.table, start=1)
elif event.clear_all:
conn.reset_sequence(self.table, start=1)
@@ -40,5 +40,5 @@
def new_oid(self, event):
assert interfaces.IGatewayEvent.isImplementedBy(event)
conn = self.get_connection(event)
- n = conn.increment(self.table)
+ n = conn.increment(self.table_name)
return str(n)
=== Products/Ape/lib/apelib/sql/properties.py 1.11 => 1.11.2.1 ===
--- Products/Ape/lib/apelib/sql/properties.py:1.11 Thu Mar 25 22:31:52 2004
+++ Products/Ape/lib/apelib/sql/properties.py Tue Jul 20 02:12:43 2004
@@ -48,24 +48,23 @@
schema.add('id', 'string', 1)
schema.add('type', 'string')
schema.add('data', 'string')
-
- table = 'properties'
- column_defs = (
- ('id', 'string', 1),
- ('type', 'string', 0),
- ('data', 'blob', 0),
- )
+ table_name = 'properties'
+ columns = [
+ Column('id', 'string', 1),
+ Column('type', 'string', 0),
+ Column('data', 'blob', 0),
+ ]
def load(self, event):
- conn = self.get_connection(event)
- rows = conn.select(self.table, self.columns, oid=event.oid)
+ table = self.get_table(event)
+ rows = table.select(self.column_names, oid=event.oid)
rows.sort()
return rows, tuple(rows)
def store(self, event, state):
- conn = self.get_connection(event)
+ table = self.get_table(event)
rows = [(id, t, data) for id, t, data in state]
- conn.set_many(self.table, event.oid, ('id',), ('type', 'data'), rows)
+ table.set_many(event.oid, ('id',), ('type', 'data'), rows)
state = list(state)
state.sort()
return tuple(state)
@@ -76,41 +75,38 @@
"""
def __init__(self, conn_name, table_name, cols):
- self.table = table_name
- self.column_defs = cols
- self.columns = [name for (name, t, u) in cols]
+ self.table_name = table_name
+ self.columns = cols
self.schema = None
SQLGatewayBase.__init__(self, conn_name)
-
def load(self, event):
- conn = self.get_connection(event)
- recs = conn.select(self.table, self.columns, oid=event.oid)
+ table = self.get_table(event)
+ recs = table.select(self.column_names, oid=event.oid)
if not recs:
return (), ()
if len(recs) > 1:
raise ValueError("Multiple records where only one expected")
record = [str(value) for value in recs[0]]
items = []
- cols = self.column_defs
+ cols = self.columns
for n in range(len(cols)):
- name, typ, unique = cols[n]
+ name = cols[n].name
if name.startswith('_'):
prop_name = name[1:]
else:
prop_name = name
- items.append((prop_name, typ, record[n]))
+ items.append((prop_name, cols[n].type, record[n]))
return items, tuple(record)
-
def store(self, event, state, leftover=None):
- cols = self.column_defs
+ cols = self.columns
statedict = {} # prop name -> (type, value)
for name, typ, value in state:
statedict[name] = (typ, value)
record = []
for col in cols:
- name = col[0]
+ name = col.name
if name.startswith('_'):
prop_name = name[1:]
else:
@@ -129,8 +125,8 @@
raise ValueError(
"Extra properties provided for fixed schema: %s"
% statedict.keys())
- conn = self.get_connection(event)
- conn.set_one(self.table, event.oid, self.columns, record, event.is_new)
+ table = self.get_table(event)
+ table.set_one(event.oid, self.column_names, record, event.is_new)
return tuple(record)
@@ -143,12 +139,12 @@
schema = SQLProperties.schema
- table = 'property_tables'
- column_defs = (
- ('class_name', 'string', 1),
- ('table_name', 'string', 0),
- )
- oid_column_def = () # No OID column
+ table_name = 'property_tables'
+ columns = [
+ Column('class_name', 'string', 1),
+ Column('table_name', 'string', 0),
+ ]
+ oid_columns = [] # No OID column
def __init__(self, conn_name='db'):
self.var_props = SQLProperties(conn_name=conn_name)
@@ -159,15 +155,15 @@
return None
def init(self, event):
- conn = self.get_connection(event)
- if not conn.exists(self.table, 'table'):
- self.create(event)
+ table = self.get_table(event)
+ if not conn.exists(table.name, 'table'):
+ table.create()
self.var_props.init(event)
if event.clear_all:
# Clear the fixed property tables.
- recs = conn.select(self.table, ('table_name',))
+ recs = table.select(('table_name',))
for (name,) in recs:
- conn.delete_from(name)
+ conn.clear_table(name)
self.fixed_props = {}
@@ -222,8 +218,9 @@
return None
# Allocate a table name
- conn = self.get_connection(event)
- rows = conn.select(self.table, ('table_name',), class_name=cn)
+ conn = self.get_connection()
+ table = self.get_table(event)
+ rows = table.select(('table_name',), class_name=cn)
if rows:
table_name = rows[0][0]
else:
@@ -237,13 +234,11 @@
if not conn.exists(table_name, 'table'):
break
attempt += 1
- conn.insert(
- self.table, ('class_name', 'table_name'), (cn, table_name))
+ table.insert(('class_name', 'table_name'), (cn, table_name))
# Create the fixed properties and table
fp = SQLFixedProperties(self.conn_name, table_name, cols)
- if not conn.exists(table_name, 'table'):
- fp.create(event)
+ fp.init(event)
# XXX If the transaction gets aborted, the table creation will
# be undone, but self.fixed_props won't see the change.
# Perhaps we need to reset self.fixed_props on abort.
@@ -252,6 +247,7 @@
def load(self, event):
+ """Returns a combination of states from two tables."""
var_state, var_hash = self.var_props.load(event)
fp = self.get_fixed_props(event)
if fp is None:
@@ -276,6 +272,7 @@
def store(self, event, state):
+ """Stores state in two tables."""
fp = self.get_fixed_props(event)
if fp is None:
return self.var_props.store(event, state)
=== Products/Ape/lib/apelib/sql/security.py 1.8 => 1.8.2.1 ===
--- Products/Ape/lib/apelib/sql/security.py:1.8 Wed Mar 24 22:17:08 2004
+++ Products/Ape/lib/apelib/sql/security.py Tue Jul 20 02:12:43 2004
@@ -31,18 +31,18 @@
schema.add('permission', 'string')
schema.add('username', 'string')
- table = 'security'
- oid_column_def = (('oid', 'int', 0),) # Don't create a primary key
+ table_name = 'security'
+ oid_columns = [Column('oid', 'int', 0)] # Don't create a primary key
def load(self, event):
- conn = self.get_connection(event)
- items = conn.select(self.table, self.columns, oid=event.oid)
+ table = self.get_table(event)
+ items = table.select(self.column_names, oid=event.oid)
items.sort()
return items, tuple(items)
def store(self, event, state):
- conn = self.get_connection(event)
- conn.set_many(self.table, event.oid, (), self.columns, state)
+ table = self.get_table(event)
+ table.set_many(event.oid, (), self.column_names, state)
state = list(state)
state.sort()
return tuple(state)
@@ -61,39 +61,43 @@
schema.add('domains', 'string:list')
table_defs = {
- 'users': (('oid', 'int', 1),
- ('id', 'string', 1),
- ('password', 'string', 0),),
- 'user_roles': (('oid', 'int', 0),
- ('id', 'string', 0),
- ('role', 'string', 0),),
- 'user_domains': (('oid', 'int', 0),
+ 'users': [Column('oid', 'int', 1),
+ Column('id', 'string', 1),
+ Column('password', 'string', 0)],
+ 'user_roles': [Column('oid', 'int', 0),
+ Column('id', 'string', 0),
+ Column('role', 'string', 0)],
+ 'user_domains': [Column('oid', 'int', 0),
('id', 'string', 0),
- ('domain', 'string', 0),),
+ ('domain', 'string', 0)],
}
def init(self, event):
conn = self.get_connection(event)
- for table, col_defs in self.table_defs.items():
- if not conn.exists(table, 'table'):
- conn.create_table(table, col_defs)
+ for table_name, columns in self.table_defs.items():
+ table = conn.define_table(table_name, columns)
+ if not table.exists():
+ table.create()
elif event.clear_all:
- conn.delete_from(table)
+ table.delete_rows()
def load(self, event):
conn = self.get_connection(event)
- rows = conn.select('users', ('id', 'password'), oid=event.oid)
+ rows = conn.get_table('users').select(
+ ('id', 'password'), oid=event.oid)
data = {}
for id, password in rows:
data[id] = (password, [], [])
- rows = conn.select('user_roles', ('id', 'role'), oid=event.oid)
+ rows = conn.get_table('user_roles').select(
+ ('id', 'role'), oid=event.oid)
for id, role in rows:
row = data.get(id)
if row is not None:
row[1].append(role)
- rows = conn.select('user_domains', ('id', 'domain'), oid=event.oid)
+ rows = conn.get_table('user_domains').select(
+ ('id', 'domain'), oid=event.oid)
for id, domain in rows:
row = data.get(id)
if row is not None:
@@ -109,7 +113,8 @@
oid = event.oid
conn = self.get_connection(event)
rows = [(id, pw) for id, pw, roles, domains in state]
- conn.set_many('users', event.oid, (), ('id', 'password',), rows)
+ conn.get_table('users').set_many(
+ event.oid, (), ('id', 'password',), rows)
roles_d = {}
domains_d = {}
for id, pw, roles, domains in state:
@@ -117,10 +122,10 @@
roles_d[(id, role)] = 1
for domain in domains:
domains_d[(id, domain)] = 1
- conn.set_many(
- 'user_roles', event.oid, (), ('id', 'role',), roles_d.keys())
- conn.set_many(
- 'user_domains', event.oid, (), ('id', 'domain',), domains_d.keys())
+ conn.get_table('user_roles').set_many(
+ event.oid, (), ('id', 'role',), roles_d.keys())
+ conn.get_table('user_domains').set_many(
+ event.oid, (), ('id', 'domain',), domains_d.keys())
state = list(state)
state.sort()
return tuple(state)
=== Products/Ape/lib/apelib/sql/sqlbase.py 1.13 => 1.13.2.1 ===
--- Products/Ape/lib/apelib/sql/sqlbase.py:1.13 Wed Mar 24 22:17:08 2004
+++ Products/Ape/lib/apelib/sql/sqlbase.py Tue Jul 20 02:12:43 2004
@@ -17,6 +17,7 @@
"""
from apelib.core.interfaces import IGateway, IDatabaseInitializer
+from apelib.core.schemas import Column
from interfaces import IRDBMSConnection
@@ -25,33 +26,40 @@
__implements__ = IGateway, IDatabaseInitializer
- table = '(override this)'
- schema = None # override
- column_defs = None # optional override
- oid_column_def = (('oid', 'int', 1),)
+ # override these in subclasses
+ table_name = None
+ schema = None
+ columns = None
+ oid_columns = [Column('oid', 'int', 1)]
def __init__(self, conn_name='db'):
self.conn_name = conn_name
- if self.column_defs is None and self.schema is not None:
- self.column_defs = tuple(self.schema.get_column_defs())
- self.columns = tuple([name for name, t, u in self.column_defs])
+ if self.columns is None:
+ if self.schema is not None:
+ self.columns = self.schema.get_columns()
+ else:
+ self.columns = []
+ self.column_names = [c.name for c in self.columns]
def get_connection(self, event):
return event.connections[self.conn_name]
+ def get_table(self, event):
+ c = event.connections[self.conn_name]
+ return c.get_table(self.table_name)
+
def create(self, event):
- conn = self.get_connection(event)
- defs = self.oid_column_def + self.column_defs
- conn.create_table(self.table, defs)
+ self.get_table(event).create()
def init(self, event):
conn = self.get_connection(event)
assert IRDBMSConnection.isImplementedBy(conn)
- if conn.exists(self.table, 'table'):
+ table = conn.define_table(self.table_name, self.columns)
+ if table.exists():
if event.clear_all:
- conn.delete_from(self.table)
+ table.delete_rows()
else:
- self.create(event)
+ table.create()
def load(self, event):
raise NotImplementedError, "abstract method"
=== Products/Ape/lib/apelib/sql/structure.py 1.11 => 1.11.2.1 ===
--- Products/Ape/lib/apelib/sql/structure.py:1.11 Sat Mar 20 01:34:23 2004
+++ Products/Ape/lib/apelib/sql/structure.py Tue Jul 20 02:12:43 2004
@@ -16,7 +16,7 @@
$Id$
"""
-from apelib.core.schemas import FieldSchema, RowSequenceSchema
+from apelib.core.schemas import FieldSchema, RowSequenceSchema, Column
from sqlbase import SQLGatewayBase
@@ -26,15 +26,15 @@
__implements__ = SQLGatewayBase.__implements__
schema = FieldSchema('data', 'string')
- table = 'object_data'
- column_defs = (
- ('data', 'blob', 0),
- )
+ table_name = 'object_data'
+ columns = [
+ Column('data', 'blob', 0),
+ ]
def load(self, event):
- conn = self.get_connection(event)
- firstcol = self.columns[:1]
- items = conn.select(self.table, firstcol, oid=event.oid)
+ table = self.get_table(event)
+ firstcol = self.column_names[:1]
+ items = table.select(firstcol, oid=event.oid)
if items:
state = items[0][0]
else:
@@ -42,10 +42,10 @@
return state, state
def store(self, event, state):
- conn = self.get_connection(event)
- firstcol = (self.column_defs[0][0],)
+ table = self.get_table(event)
+ firstcol = self.column_names[:1]
data = (conn.module.Binary(state),)
- conn.set_one(self.table, event.oid, firstcol, data, event.is_new)
+ table.set_one(event.oid, firstcol, data, event.is_new)
return state
@@ -58,16 +58,15 @@
schema.add('key', 'string', 1)
schema.add('oid', 'string')
schema.add('classification', 'classification')
-
- table = 'folder_items'
- column_defs = (
- ('name', 'string', 1),
- ('child_oid', 'int', 0),
- )
+ table_name = 'folder_items'
+ columns = [
+ Column('name', 'string', 1),
+ Column('child_oid', 'int', 0),
+ ]
def load(self, event):
- conn = self.get_connection(event)
- rows = conn.select(self.table, self.columns, oid=event.oid)
+ table = self.get_table(event)
+ rows = table.select(self.columns, oid=event.oid)
res = []
h = []
for name, child_oid in rows:
@@ -79,12 +78,12 @@
return res, tuple(h)
def store(self, event, state):
- conn = self.get_connection(event)
+ table = self.get_table(event)
rows = [(name, long(child_oid)) for (name, child_oid, cls) in state]
rows.sort()
# Note that set_many() requires the child_oid column to match
# its database type.
- conn.set_many(self.table, event.oid, ('name',), ('child_oid',), rows)
+ table.set_many(event.oid, ('name',), ('child_oid',), rows)
return tuple(rows)
@@ -98,19 +97,18 @@
__implements__ = SQLGatewayBase.__implements__
schema = FieldSchema('id', 'string')
- table = 'folder_items'
-
- column_defs = (
- ('child_oid', 'int', 1),
- ('name', 'string', 0),
- )
+ table_name = 'folder_items'
+ columns = [
+ Column('child_oid', 'int', 1),
+ Column('name', 'string', 0),
+ ]
def init(self, event):
pass
def load(self, event):
- conn = self.get_connection(event)
- rows = conn.select(self.table, ('name',), child_oid=event.oid)
+ table = self.get_table(event)
+ rows = table.select(('name',), child_oid=event.oid)
if len(rows) >= 1:
name = rows[0][0] # Accept only the first result
else:
@@ -127,10 +125,10 @@
__implements__ = SQLGatewayBase.__implements__
- table = 'remainder'
- column_defs = (
- ('pickle', 'blob', 0),
- )
+ table_name = 'remainder'
+ columns = [
+ Column('pickle', 'blob', 0),
+ ]
class SQLModTime (SQLGatewayBase):
@@ -139,14 +137,14 @@
__implements__ = SQLGatewayBase.__implements__
schema = FieldSchema('mtime', 'int') # second
- table = 'mtime'
- column_defs = (
- ('mtime', 'long', 0),
- )
+ table_name = 'mtime'
+ columns = [
+ Column('mtime', 'long', 0),
+ ]
def load(self, event):
- conn = self.get_connection(event)
- items = conn.select(self.table, self.columns, oid=event.oid)
+ table = self.get_table(event)
+ items = table.select(self.columns, oid=event.oid)
if items:
state = long(items[0][0])
else:
@@ -155,9 +153,9 @@
def store(self, event, state):
state = long(state)
- conn = self.get_connection(event)
+ table = self.get_table(event)
data = (state,)
- conn.set_one(self.table, event.oid, self.columns, data, event.is_new)
+ table.set_one(event.oid, self.columns, data, event.is_new)
return state
More information about the Zope-CVS
mailing list