Пример #1
0
 def validateSubtree(self, context: StatementContext, relexpr):
     self.inputs[0].validateSubtree(context, relexpr)
     try:
         self.type = context.check.function_call(symbolic(self.op),
                                                 [self.inputs[0].type])
     except TypeSysError as e:
         raise ValidationError(str(e), self, relexpr) from e
Пример #2
0
 def info(self):
     yield '{} => {}'.format(symbolic(sym.AGGR), self.type)
     for groupby in self.groupbys:
         yield '|group by: ' + groupby.info()
     for aggr in self.aggrs:
         yield '|' + aggr.info()
     for i, line in enumerate(self.inputs[0].info()):
         yield ('\\_' if i == 0 else '  ') + line
Пример #3
0
    def validateSubtree(self, context: StatementContext):
        self.inputs[0].validateSubtree(context)
        self.inputs[1].validateSubtree(context)
        if self.cond is None:
            self.pairs = list()
            for i0, a0 in enumerate(self.inputs[0].type.attrs):
                if a0.name is None:
                    continue
                matches = [(i1, a1) for i1, a1 in enumerate(self.inputs[1].type.attrs)\
                           if a0.name == a1.name]
                if len(matches) > 1:
                    raise self.validationError('ambiguity in natural join: {} from the left input'
                                               ' matches multiple attributes on the right'\
                                               .format(a0.str_ref_only()))

                elif len(matches) == 1:
                    i1, a1 = matches[0]
                    try:
                        context.check.function_call(symbolic(sym.EQ), [a0.type, a1.type])
                    except TypeSysError as e:
                        raise self.validationError('natural join cannot equate {} and {}'\
                                                   .format(a0, a1))
                    self.pairs.append((i0, i1))
            if len(self.pairs) == 0:
                logger.warning('{}: no attributes with matching names found;'
                               ' natural join degnerates into cross product'.format(self))
            for i0, i1 in self.pairs:
                if any((j0, j1) for j0, j1 in self.pairs if j0 != i0 and j1 == i1):
                    raise self.validationError('ambiguity in natural join: {} from the right input'
                                               ' matches multiple attributes on the left'\
                                               .format(self.inputs[1].type.attrs[i1]\
                                                       .str_ref_only()))
            attrspecs = list()
            for a0 in self.inputs[0].type.attrs:
                attrspecs.append(a0)
            for i1, a1 in enumerate(self.inputs[1].type.attrs):
                if not any(i1 == i for _, i in self.pairs):
                    attrspecs.append(a1)
                    if any(a1.can_be_confused_with(a0) for a0 in self.inputs[0].type.attrs):
                        # this shouldn't happen under natural join rule, but oh well:
                        logger.warning('{}: attribute {} becomes confused with others'
                                       ' in the join output'\
                                       .format(self, a1.str_ref_only()))
            self.type = RelType(context.new_tmp(), attrspecs)
        else:
            self.cond.validateSubtree(context, self)
            if self.cond.type != ValType.BOOLEAN:
                raise self.validationError('join condition {} has type {}; boolean expected'\
                                           .format(self.cond, self.cond.type.value))
            for a0, a1 in itertools.product(self.inputs[0].type.attrs, self.inputs[1].type.attrs):
                if a0.can_be_confused_with(a1):
                    logger.warning('{}: attributes {} from the left input and {} from the right'
                                   ' become confused in the join output'\
                                   .format(self, a0.str_ref_only(), a1.str_ref_only()))
            self.type = RelType(context.new_tmp(),
                                self.inputs[0].type.attrs + self.inputs[1].type.attrs)
Пример #4
0
 def info(self):
     yield '{} => {}'.format(symbolic(sym.JOIN), self.type)
     if self.cond is not None:
         yield '|' + self.cond.info()
     elif len(self.pairs) == 0:
         yield '|inferred: cross product with no join condition'
     else:
         for i0, i1 in self.pairs:
             yield '|inferred: {}[0.{}] = {}[1.{}]'\
                 .format(self.inputs[0].type.attrs[i0].str_ref_only(), i0,
                         self.inputs[1].type.attrs[i1].str_ref_only(), i1)
     for i, line in enumerate(self.inputs[0].info()):
         yield ('\\_' if i == 0 else '| ') + line
     for i, line in enumerate(self.inputs[1].info()):
         yield ('\\_' if i == 0 else '  ') + line
Пример #5
0
 def info(self):
     yield lreplace(str(self), literal(sym.SOURCE), symbolic(sym.SOURCE))
Пример #6
0
 def info(self):
     yield lreplace(str(self), literal(sym.CLEAR), symbolic(sym.CLEAR))
Пример #7
0
 def info(self):
     yield symbolic(self.cmd)
Пример #8
0
 def info(self):
     yield '{} => {}'.format(symbolic(self.op()), self.type)
     for i, line in enumerate(self.inputs[0].info()):
         yield ('\\_' if i == 0 else '| ') + line
     for i, line in enumerate(self.inputs[1].info()):
         yield ('\\_' if i == 0 else '  ') + line
Пример #9
0
 def info(self):
     yield '{} => {}'.format(symbolic(sym.SELECT), self.type)
     yield '|' + self.cond.info()
     for i, line in enumerate(self.inputs[0].info()):
         yield ('\\_' if i == 0 else '  ') + line
Пример #10
0
 def info(self):
     yield '{} => {}'.format(symbolic(sym.PROJECT), self.type)
     for attr in self.attrs:
         yield '|' + attr.info()
     for i, line in enumerate(self.inputs[0].info()):
         yield ('\\_' if i == 0 else '  ') + line
Пример #11
0
 def info(self):
     yield symbolic(sym.SQLEXEC) + ': ' + self.sql