1
# -*- test-case-name: twisted.test.test_reflector -*-
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
# See LICENSE for details.
8
from twisted.enterprise.util import DBError
11
"""Base class for enterprise reflectors. This implements row caching.
15
def __init__(self, rowClasses):
17
Initialize me against a database.
19
@param rowClasses: a list of row class objects that describe the
23
self.rowCache = weakref.WeakValueDictionary() # does not hold references to cached rows.
24
self.rowClasses = rowClasses
28
def __getstate__(self):
29
d = self.__dict__.copy()
33
def __setstate__(self, state):
35
self.rowCache = weakref.WeakValueDictionary()
39
"""Implement me to populate schema information for the reflector.
41
raise DBError("not implemented")
43
def populateSchemaFor(self, tableInfo):
44
"""This is called once for each registered rowClass to add it
45
and its foreign key relationships for that rowClass to the
48
self.schema[ tableInfo.rowTableName ] = tableInfo
50
# add the foreign key to the foreign table.
51
for foreignTableName, childColumns, parentColumns, containerMethod, autoLoad in tableInfo.rowForeignKeys:
52
self.schema[foreignTableName].addForeignKey(childColumns,
53
parentColumns, tableInfo.rowClass,
54
containerMethod, autoLoad)
56
def getTableInfo(self, rowObject):
57
"""Get a TableInfo record about a particular instance.
59
This record contains various information about the instance's
60
class as registered with this reflector.
62
@param rowObject: a L{RowObject} instance of a class previously
64
@raises twisted.enterprise.row.DBError: raised if this class was not
65
previously registered.
68
return self.schema[rowObject.rowTableName]
70
raise DBError("class %s was not registered with %s" % (
71
rowObject.__class__, self))
73
def buildWhereClause(self, relationship, row):
74
"""util method used by reflectors. builds a where clause to link a row to another table.
77
for i in range(0,len(relationship.childColumns)):
78
value = getattr(row, relationship.parentColumns[i][0])
79
whereClause.append( [relationship.childColumns[i][0], EQUAL, value] )
82
def addToParent(self, parentRow, rows, tableName):
83
"""util method used by reflectors. adds these rows to the parent row object.
84
If a rowClass does not have a containerMethod, then a list attribute "childRows"
87
parentInfo = self.getTableInfo(parentRow)
88
relationship = parentInfo.getRelationshipFor(tableName)
90
raise DBError("no relationship from %s to %s" % ( parentRow.rowTableName, tableName) )
92
if not relationship.containerMethod:
93
if hasattr(parentRow, "childRows"):
95
if row not in parentRow.childRows:
96
parentRow.childRows.append(row)
98
parentRow.childRows = rows
101
if not hasattr(parentRow, relationship.containerMethod):
102
raise DBError("parent row (%s) doesnt have container method <%s>!" % (parentRow, relationship.containerMethod))
104
meth = getattr(parentRow, relationship.containerMethod)
108
####### Row Cache ########
110
def addToCache(self, rowObject):
111
"""NOTE: Should this be recursive?! requires better container knowledge..."""
112
self.rowCache[ rowObject.getKeyTuple() ] = rowObject
114
def findInCache(self, rowClass, kw):
116
keys.append(rowClass.rowTableName)
117
for keyName, keyType in rowClass.rowKeyColumns:
118
keys.append( kw[keyName] )
119
keyTuple = tuple(keys)
120
return self.rowCache.get(keyTuple)
122
def removeFromCache(self, rowObject):
123
"""NOTE: should this be recursive!??"""
124
key = rowObject.getKeyTuple()
125
if self.rowCache.has_key(key):
126
del self.rowCache[key]
128
####### Row Operations ########
130
def loadObjectsFrom(self, tableName, parent=None, data=None,
131
whereClause=[], loadChildren=1):
132
"""Implement me to load objects from the database.
134
@param whereClause: a list of tuples of (columnName, conditional, value)
135
so it can be parsed by all types of reflectors. eg.::
136
whereClause = [("name", EQUALS, "fred"), ("age", GREATERTHAN, 18)]
138
raise DBError("not implemented")
140
def updateRow(self, rowObject):
141
"""update this rowObject to the database.
143
raise DBError("not implemented")
145
def insertRow(self, rowObject):
146
"""insert a new row for this object instance.
148
raise DBError("not implemented")
150
def deleteRow(self, rowObject):
151
"""delete the row for this object from the database.
153
raise DBError("not implemented")
162
__all__ = ['Reflector', 'EQUAL', 'LESSTHAN', 'GREATERTHAN', 'LIKE']