# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------
"""
AdaptorChannel
CVS information
$Id: AdaptorChannel.py 932 2004-07-20 06:21:57Z sbigaret $
"""
__version__='$Revision: 932 $'[11:-2]
from logging import warn,debug
import traceback, StringIO
# Framework
from DatabaseOperation import \
ADAPTOR_LOCK_OPERATOR, \
ADAPTOR_INSERT_OPERATOR, \
ADAPTOR_UPDATE_OPERATOR, \
ADAPTOR_DELETE_OPERATOR, \
ADAPTOR_STORED_PROCEDURE_OPERATOR
from Adaptor import GeneralAdaptorException
# Interfaces
from Modeling.interfaces.AdaptorChannel import IAdaptorChannel
# Notifications
AdaptorChannelBeginTransactionNotification='AdaptorChannelBeginTransactionNotification'
AdaptorChannelCommitTransactionNotification='AdaptorChannelCommitTransactionNotification'
AdaptorChannelRollbackTransactionNotification='AdaptorChannelRollbackTransactionNotification'
#
class AdaptorChannel:
"See interfaces.AdaptorChannel for details"
__implements__ = (IAdaptorChannel,)
def __init__(self, anAdaptorContext):
"See interfaces.AdaptorChannel for details"
self._adaptorContext=anAdaptorContext
self._delegate=None
def adaptorContext(self):
"See interfaces.AdaptorChannel for details"
return self._adaptorContext
def addStoredProceduresNamed(self, storedProcedureNames, aModel):
"See interfaces.AdaptorChannel for details"
def attributesToFetch(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def cancelFetch(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def closeChannel(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def delegate(self):
"See interfaces.AdaptorChannel for details"
return self._delegate
def deleteRowDescribedByQualifier(self, aQualifier, anEntity):
"""
Calls 'deleteRowsDescribedByQualifier()' on itself and make sure that one
and only one row was deleted. If the returned value from
'deleteRowsDescribedByQualifier()' is not one, it raises
GeneralAdaptorException.
Subclasses should not override this method.
Parameters: see deleteRowsDescribedByQualifier()
"""
nbDeletedRows=self.deleteRowsDescribedByQualifier(aQualifier, anEntity)
if nbDeletedRows>1:
raise GeneralAdaptorException, 'deleted more than one row'
def deleteRowsDescribedByQualifier(self, aQualifier, anEntity):
"""
Implemented by subclasses to delete the rows identified by the parameters.
This method returns the number of rows deleted.
Parameters:
aQualifier -- a Qualifier object describing the rows to delete
anEntity -- the Entity corresponding to the type of the objects
to-be-deleted (hence, identifies the database table from which rows
should be deleted)
See also: deleteRowDescribedByQualifier(), performAdaptorOperation()
"""
__abstract__()
def describeModelWithTableNames(self, tableNames):
"See interfaces.AdaptorChannel for details"
__abstract__()
def describeResults(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def describeStoredProcedureNames(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def describeTableNames(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def dictionaryWithObjectsForAttributes(self, objects, attributes):
"See interfaces.AdaptorChannel for details"
def evaluateExpression(self, anSQLexpression):
"""
Extract the SQL statement from 'anSQLexpression' and sends it to the
database for execution.
If its AdaptorContext did not have an opened transaction when this method
is called, it should automatically start a new transaction which is ended
before the method returns.
Parameter:
anSQLexpression -- the SQLExpression object to execute
See also: SQLExpression.statement(), AdaptorContext.hasOpenTransaction()
"""
__abstract__()
def executeStoredProcedure(self, aStoredProcedure, values):
"See interfaces.AdaptorChannel for details"
__abstract__()
def fetchRow(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def insertRow(self, row, anEntity):
"See interfaces.AdaptorChannel for details"
__abstract__()
def isFetchInProgress(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def isOpen(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def lockRowComparingAttributes(self, atts, anEntity, aQualifier, snapshot):
"See interfaces.AdaptorChannel for details"
self.__unimplemented__()
def openChannel(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def performAdaptorOperation(self, anAdaptorOperation):
"""
Examines 'anAdaptorOperation' and executes the corresponding method.
Given that 'operator' is anAdaptorOperation.operator(), and that constants
used below (such as 'ADAPTOR_INSERT_OPERATOR') are defined in class
DatabaseOperation, this is how things work:
- if 'operator' is 'ADAPTOR_INSERT_OPERATOR', we call insertRow()
- if 'operator' is 'ADAPTOR_DELETE_OPERATOR', we call
deleteRowDescribedByQualifier()
- 'operator' is 'ADAPTOR_UPDATE_OPERATOR', we call
updateValuesInRowDescribedByQualifier()
Subclasses should not override this method.
Raises GeneralAdaptorException in case of failure
Parameter:
adaptorOperation -- the AdaptorOperation to execute
See also: performAdaptorOperations(), DatabaseOperation
"""
self.openChannel()
operator=anAdaptorOperation.adaptorOperator()
if operator is ADAPTOR_INSERT_OPERATOR:
self.insertRow(anAdaptorOperation.changedValues(),
anAdaptorOperation.entity())
elif operator is ADAPTOR_DELETE_OPERATOR:
self.deleteRowDescribedByQualifier(anAdaptorOperation.qualifier(),
anAdaptorOperation.entity())
elif operator is ADAPTOR_UPDATE_OPERATOR:
self.updateValuesInRowDescribedByQualifier(anAdaptorOperation.changedValues(), anAdaptorOperation.qualifier(), anAdaptorOperation.entity())
else:
raise ValueError, \
"Unsupported AdaptorOperation's operation (%s)"%operator
def performAdaptorOperations(self, adaptorOperations):
"""
Iterates on each item in 'adaptorOperations' and calls
'performAdaptorOperation()' with that item as a parameter.
Subclasses should not override this method.
Parameter:
adaptorOperations -- a sequence of AdaptorOperation objects
"""
try:
for adOp in adaptorOperations:
self.performAdaptorOperation(adOp)
except GeneralAdaptorException:
#if 1: # __TBD if DEBUG (somehow)
# exc=StringIO.StringIO()
# traceback.print_exc(file=exc)
# debug(exc.getvalue())
# del exc
warn('Got an error ; this should be logged & returned')
raise
def primaryKeysForNewRowsWithEntity(self, count, anEntity):
"See interfaces.AdaptorChannel for details"
__abstract__()
def returnValuesForLastStoredProcedureInvocation(self):
"See interfaces.AdaptorChannel for details"
__abstract__()
def rowCountForSelectAttributes(self, attributes, aFetchSpecification,
shouldLock, anEntity):
"""
Implemented by concrete adaptors to return the number of rows that would
be fetched if selectAttributes() is called with the same arguments.
Parameters: see selectAttributes()
See also: SQLExpression.prepareSelectCountExpressionWithAttributes()
"""
__abstract__()
def selectAttributes(self, attributes, aFetchSpecification, shouldLock,
anEntity):
"See interfaces.AdaptorChannel for details"
__abstract__()
def setAttributesToFetch(self, attributes):
"See interfaces.AdaptorChannel for details"
self.__unimplemented__()
def setDelegate(self, aDelegate):
"See interfaces.AdaptorChannel for details"
self._delegate=aDelegate
def updateValuesInRowDescribedByQualifier(self, row, aQualifier, anEntity):
"""
Calls 'updateValuesInRowsDescribedByQualifier' on itself and make sure
that one and only one row was updated. If the returned value from
'updateValuesInRowsDescribedByQualifier' is not exactly one, it raises
GeneralAdaptorException.
Subclasses should not override this method.
Parameters: see updateValuesInRowsDescribedByQualifier
"""
nbUpdatedRows=self.updateValuesInRowsDescribedByQualifier(row,
aQualifier,
anEntity)
if nbUpdatedRows>1:
raise GeneralAdaptorException, 'updated more than one row'
def updateValuesInRowsDescribedByQualifier(self, row, aQualifier, anEntity):
"""
Implemented by subclasses to update the rows identified by the parameters.
This method returns the number of updated rows.
Parameters:
row --
aQualifier -- a Qualifier object describing the rows to update
anEntity -- the Entity corresponding to the type of the objects to be
updated (hence, identifies the database table from which rows should
be updated)
See also: updateValuesInRowDescribedByQualifier(),
performAdaptorOperation()
Returns: the number of updated rows
"""
__abstract__()
def __unimplemented__(self):
"-"
raise 'Unimplemented'
def __abstract__():
raise 'AbstractMethod', 'Left intentionally unimplemented in this class, '\
'subclass should override this method'
|