def addToParent(self, parentRow, rows, tableName): """util method used by reflectors. adds these rows to the parent row object. If a rowClass does not have a containerMethod, then a list attribute "childRows" will be used. """ parentInfo = self.getTableInfo(parentRow) relationship = parentInfo.getRelationshipFor(tableName) if not relationship: raise DBError("no relationship from %s to %s" % (parentRow.rowTableName, tableName)) if not relationship.containerMethod: if hasattr(parentRow, "childRows"): for row in rows: if row not in parentRow.childRows: parentRow.childRows.append(row) else: parentRow.childRows = rows return if not hasattr(parentRow, relationship.containerMethod): raise DBError( "parent row (%s) doesnt have container method <%s>!" % (parentRow, relationship.containerMethod)) meth = getattr(parentRow, relationship.containerMethod) for row in rows: meth(row)
def findAttribute(self, attrName): """Find an attribute by caseless name. """ for attr, type in self.rowColumns: if attr.lower() == attrName.lower(): return getattr(self, attr) raise DBError("Unable to find attribute %s" % attrName)
def _transPopulateSchema(self): """Used to construct the row classes in a single interaction. """ for rc in self.rowClasses: if not issubclass(rc, RowObject): raise DBError("Stub class (%s) is not derived from RowObject" % reflect.qual(rc.rowClass)) self._populateSchemaFor(rc) self.populated = 1
def assignKeyAttr(self, attrName, value): """Assign to a key attribute. This cannot be done through normal means to protect changing keys of db objects. """ found = 0 for keyColumn, type in self.rowKeyColumns: if keyColumn == attrName: found = 1 if not found: raise DBError("%s is not a key columns." % attrName) self.__dict__[attrName] = value
def loadObjectsFrom(self, tableName, parent=None, data=None, whereClause=[], loadChildren=1): """Implement me to load objects from the database. @param whereClause: a list of tuples of (columnName, conditional, value) so it can be parsed by all types of reflectors. eg.:: whereClause = [("name", EQUALS, "fred"), ("age", GREATERTHAN, 18)] """ raise DBError("not implemented")
def __setattr__(self, name, value): """Special setattr to prevent changing of key values. """ # build where clause if getKeyColumn(self.__class__, name): raise DBError( "cannot assign value <%s> to key column attribute <%s> of RowObject class" % (value, name)) if name in self.rowColumns: if value != self.__dict__.get(name, None) and not self.dirty: self.setDirty(1) self.__dict__[name] = value
def _populateSchemaFor(self, rc): """Construct all the SQL templates for database operations on <tableName> and populate the class <rowClass> with that info. """ attributes = ("rowColumns", "rowKeyColumns", "rowTableName" ) for att in attributes: if not hasattr(rc, att): raise DBError("RowClass %s must have class variable: %s" % (rc, att)) tableInfo = _TableInfo(rc) tableInfo.updateSQL = self.buildUpdateSQL(tableInfo) tableInfo.insertSQL = self.buildInsertSQL(tableInfo) tableInfo.deleteSQL = self.buildDeleteSQL(tableInfo) self.populateSchemaFor(tableInfo)
def loadObjectsFrom(self, tableName, parentRow = None, data = None, whereClause = None, forceChildren = 1): """The whereClause for XML loading is [(columnName, operation, value)] list of tuples """ if parentRow and whereClause: raise DBError("Must specify one of parentRow _OR_ whereClause") if parentRow: info = self.getTableInfo(parentRow) relationship = info.getRelationshipFor(tableName) whereClause = self.buildWhereClause(relationship, parentRow) elif whereClause: pass else: whereClause = [] results = self._rowLoader(tableName, parentRow, data, whereClause, forceChildren) return defer.succeed(results)
def getTableInfo(self, rowObject): """Get a TableInfo record about a particular instance. This record contains various information about the instance's class as registered with this reflector. @param rowObject: a L{RowObject} instance of a class previously registered with me. @raises twisted.enterprise.row.DBError: raised if this class was not previously registered. """ try: return self.schema[rowObject.rowTableName] except KeyError: raise DBError("class %s was not registered with %s" % (rowObject.__class__, self))
def loadObjectsFrom(self, tableName, parentRow=None, data=None, whereClause=None, forceChildren=0): """Load a set of RowObjects from a database. Create a set of python objects of <rowClass> from the contents of a table populated with appropriate data members. Example:: | class EmployeeRow(row.RowObject): | pass | | def gotEmployees(employees): | for emp in employees: | emp.manager = "fred smith" | manager.updateRow(emp) | | reflector.loadObjectsFrom("employee", | data = userData, | whereClause = [("manager" , EQUAL, "fred smith")] | ).addCallback(gotEmployees) NOTE: the objects and all children should be loaded in a single transaction. NOTE: can specify a parentRow _OR_ a whereClause. """ if parentRow and whereClause: raise DBError("Must specify one of parentRow _OR_ whereClause") if parentRow: info = self.getTableInfo(parentRow) relationship = info.getRelationshipFor(tableName) whereClause = self.buildWhereClause(relationship, parentRow) elif whereClause: pass else: whereClause = [] return self.dbpool.runInteraction(self._rowLoader, tableName, parentRow, data, whereClause, forceChildren)
def _populate(self): """Implement me to populate schema information for the reflector. """ raise DBError("not implemented")
def deleteRow(self, rowObject): """delete the row for this object from the database. """ raise DBError("not implemented")
def insertRow(self, rowObject): """insert a new row for this object instance. """ raise DBError("not implemented")
def updateRow(self, rowObject): """update this rowObject to the database. """ raise DBError("not implemented")