class RelationVisitor(QueryVisitor): ''' will record all relation definitions and create them ''' def __init__(self, joinBuilder, alu): ''' @param joinBuilder: a visitor that has to be also visiting the AST. @type joinBuilder: JoinBuilder @param alu: the ALU to be used to operate @type alu: ALU ''' super(RelationVisitor, self).__init__() self._logic = LogicBuilder(alu) self._join = joinBuilder self._expr = ExpressionEvalBuilder(alu) self._alu = alu self._log = logging.getLogger(__name__+'.'+self.__class__.__name__) self._actualRelationName = None self._actualSelection = None self._actualProjection = None self._actualSource = None self._actualInputs = None self._active = False self._exprStack = None # a stack on which projection are pushed. self._logicFound = False # have we traversed any logic since last reset. self._relations = dict() self._inserts = list() self._log.info('init') def getRelations(self): ''' returns all relations that have been found while traversing ''' return self._relations def getInserts(self): ''' returns all inserts that have been seen while traversing. ''' return self._inserts def enterTableCreation(self, name): self._active = True self._actualRelationName = name self._actualSelection = None self._actualProjection = None self._actualSource = None def leaveTableCreation(self): self._active = False if self._actualRelationName is None: raise InternalError('rel name is None') if self._definedRelation is None: raise InternalError('select without a source') relation = TableOperator() self._definedRelation.addListener(relation) self._relations[self._actualRelationName] = relation for (name, rel) in self._actualInputs: relation.addSource(name, rel) self._actualRelationName = None self._actualInputs = list() def enterInsertStmt(self): self._active = True self._actualRelationName = None def leaveInsertStmt(self): self._active = False if self._actualRelationName is None: raise InternalError('rel name is None') if self._definedRelation is None: raise InternalError() relation = TableOperator() self._definedRelation.addListener(relation) self._inserts.append((self._actualRelationName,relation)) for (name, rel) in self._actualInputs: relation.addSource(name, rel) self._actualRelationName = None self._actualInputs = list() def setTargetRelation(self, name): if not self._active: return self._actualRelationName = name def enterSelectStmt(self): if not self._active: return self._actualSelection = None self._actualProjection = None self._actualSource = None self._definedRelation = None def leaveSelectStmt(self): if not self._active: return relation = self._actualSource if self._actualSelection is not None: relation.addListener(self._actualSelection) relation = self._actualSelection if self._actualProjection is not None: relation.addListener(self._actualProjection) relation = self._actualProjection self._definedRelation = relation self._actualSelection = None self._actualProjection = None self._actualSource = None def leaveSourceRelation(self): if not self._active: return self._actualSource = self._join.getResult() self._actualInputs = [] for (name, rel) in self._join.getInputRelations(): self._actualInputs.append((name, rel)) def enterSelection(self): if not self._active: return self._actualSelection = None self._logicFound = False def leaveSelection(self): if not self._active: return if not self._logicFound: return tmp = SelectionOperator() tmp.init(self._logic.getResult()) self._actualSelection = tmp def enterProjection(self, distinct): if self._actualProjection is None: self._actualProjection = ProjectionOperator(self._alu) self._actualProjection.setDistinct(distinct) def leaveProjection(self): if self._actualProjection is None: # no projections defined return if self._actualProjection.isFullProjection(): self._actualProjection = None def enterRename(self): pass def leaveRename(self): path = self._exprStack[0] expr = self._exprStack[1] self._exprStack = None self._actualProjection.addProjection(path, expr) def acceptLogic(self, logic): if not self._active: return self._logicFound = True logic.walk(self._logic) def acceptExpression(self, expr): if self._actualProjection is None: return if self._exprStack is None: self._exprStack = list() self._exprStack.append(expr) else: expr.walk(self._expr) self._exprStack.append(self._expr.getResult())
def enterProjection(self, distinct): if self._actualProjection is None: self._actualProjection = ProjectionOperator(self._alu) self._actualProjection.setDistinct(distinct)