示例#1
0
    def clean(self):
        self.qtable_list = None
        if filter(None, [not f.is_valid() for f in self.forms]):
            return

        qt_by_name = {}  # Dictionary of name -> [ QTable list ]
        n_display = 0
        for form in self.forms:
            if form.cleaned_data['display']:
                n_display += 1

            # Gather a list of QTables (qtable_list) involved, and check for naming collision
            if form.cleaned_data['source'] != 'table':
                continue

            curr = form.qtable
            qt_list = qt_by_name.get(curr.name, [])
            for qt in qt_list:
                # Error if a table has alias but another doesn't. (Tables with the same name.)
                if bool(curr.alias) ^ bool(qt.alias):
                    raise forms.ValidationError(
                        'Ambiguous table "%s" without alias' % (qt.name, ))
                if curr.alias == qt.alias:
                    # Duplicate. Don't update.
                    break
            else:
                qt_list.append(curr)
                qt_by_name[curr.name] = qt_list

        self.qtable_list = sum([tbl_list for tbl_list in qt_by_name.values()],
                               [])
        if not self.qtable_list:
            raise forms.ValidationError('Not selecting from any table column')
        if n_display == 0:
            raise forms.ValidationError('Not displaying any selection')
示例#2
0
    def clean(self):
        self.qtable = None
        self.selection = None

        self._display_check()

        if self.cleaned_data.get('sort') and not self.cleaned_data['sort_hql']:
            raise KeyError()

        # Verify that the 'source' field is consistent with the other fields
        source = self.cleaned_data.get('source')
        if not source:
            return None  # No point since we can't get source

        constant_val = self.cleaned_data.get('constant')
        _field_source_check(source,
                            'Constant',
                            constant_val,
                            is_from_table=False)

        table_val = self.cleaned_data.get('table')
        _field_source_check(source,
                            'From table',
                            table_val,
                            is_from_table=True)

        col_val = self.cleaned_data.get('col')
        _field_source_check(source, 'From column', col_val, is_from_table=True)

        if self.cleaned_data.get(
                'sort', '') and not self.cleaned_data.get('sort_order', ''):
            raise forms.ValidationError('Sort order missing')

        if table_val:
            # Column must belong to the table
            self.qtable = report_gen.QTable(
                table_val, self.cleaned_data.get('table_alias'))
            if col_val == '*':
                if self.cleaned_data.get('col_alias'):
                    raise forms.ValidationError(
                        'Alias not applicable for selecting "*"')
            elif col_val not in self.qtable.get_columns():
                raise forms.ValidationError('Invalid column name "%s"' %
                                            (col_val, ))
            # ColumnSelection object
            self.selection = report_gen.ColumnSelection(
                self.qtable, col_val, self.cleaned_data.get('col_alias'))
        else:
            # ConstSelection object
            self.selection = report_gen.ConstSelection(
                constant_val, self.cleaned_data.get('col_alias'))
        self.selection.distinct = self.cleaned_data.get('distinct', False)
        self.selection.set_aggregation(self.cleaned_data.get('agg', ''))

        if self.errors:
            delattr(self, 'selection')
        return self.cleaned_data
示例#3
0
    def clean(self):
        if self.errors:
            return

        # Verify unary operators constraints
        check_right = True
        op = self.cleaned_data['op']
        if op in common.RELATION_OPS_UNARY:
            if self.cleaned_data.get('r_source') or self.cleaned_data.get(
                    'r_cond'):
                raise forms.ValidationError(
                    'Operator %s does not take the right operand' % (op, ))
            check_right = False
        else:
            if not self.cleaned_data.get(
                    'l_source') or not self.cleaned_data.get('r_source'):
                raise forms.ValidationError('Operator %s takes both operands' %
                                            (op, ))

        # Verify the lhs values match the source
        l_source = self.cleaned_data['l_source']
        l_constant = self.cleaned_data.get('l_constant')
        _field_source_check(l_source,
                            'Constant (Left)',
                            l_constant,
                            is_from_table=False)
        l_table = self.cleaned_data.get('l_table')
        _field_source_check(l_source,
                            'Table (Left)',
                            l_table,
                            is_from_table=True)
        l_col = self.cleaned_data.get('l_col')
        _field_source_check(l_source,
                            'Column (Left)',
                            l_col,
                            is_from_table=True)

        if check_right:
            # Verify the rhs values match the source
            r_source = self.cleaned_data['r_source']
            r_constant = self.cleaned_data.get('r_constant')
            _field_source_check(r_source,
                                'Constant (Right)',
                                r_constant,
                                is_from_table=False)
            r_table = self.cleaned_data.get('r_table')
            _field_source_check(r_source,
                                'Table (Right)',
                                r_table,
                                is_from_table=True)
            r_col = self.cleaned_data.get('r_col')
            _field_source_check(r_source,
                                'Column (Right)',
                                r_col,
                                is_from_table=True)
        return self.cleaned_data
示例#4
0
 def _display_check(self):
     """Reconcile 'display' with 'source'"""
     src = self.cleaned_data.get('source')
     if not self.cleaned_data.get('display'):
         if src and src != 'table':
             raise forms.ValidationError(
                 'Source must be "table" when not displaying column')
         self.cleaned_data['source'] = 'table'
         if self.cleaned_data.get('col_alias'):
             raise forms.ValidationError(
                 'Column alias not applicable when not displaying column')
     else:
         if not src:
             raise forms.ValidationError('Source value missing')
示例#5
0
def _field_source_check(true_source, field_name, field_value, is_from_table):
    """
  Some fields come from a table (is_from_table). And they should be specified iff
  the true_source (what the user selected) says "table". The same holds for constant
  source. This function verifies that constraint and would raise ValidationError.

  Returns whether this field is required.
  """
    if bool(true_source == 'table') ^ bool(is_from_table):
        if field_value:
            raise forms.ValidationError(
                '%s value not applicable with %s source' %
                (field_name, true_source))
        return False
    elif not field_value:
        raise forms.ValidationError('%s value missing' % (field_name, ))
    return True
示例#6
0
def fixup_union(parent_mform, subform_name, data, is_root=False):
    """
  Create child union mforms dynamically. Note that the parent_mform may be invalid.
  The parent_mform is a MultiForm, in which the subform_name is a UnionMultiForm we
  need to fix.

  This method performs this dynamic construction of the child UnionMultiForm.
  Note that it applies to existing child forms (i.e. the child form exists and the
  user is submitting the query), as well as a newly added child (i.e. the user just
  clicked 'ADD' to add a sub-condition).

  We figure out the number of children from the mgmt form. Note that this is actually
  a count of the number of children we have ever had. It is a max of the number of
  children, some of which may have been deleted.

  For each child <i>, our strategy is to test if 'sub<i>' exists in the POST data.
  If so, we create a sub-UnionMultiForm for that child. And we do it recursively.
  """
    global SUB_UNION_PREFIX

    union_mform = getattr(parent_mform, subform_name)
    mgmt_form = union_mform.mgmt
    if not mgmt_form.is_valid():
        raise forms.ValidationError('Missing ManagementForm for conditions')
    n_children = mgmt_form.form_counts()

    # This removes our current subform (union_mform) and any children.
    if mgmt_form.cleaned_data['remove']:
        parent_mform.remove_subform(subform_name)
        LOG.debug('Removed subform: %s' % (union_mform, ))
        # If we just removed the root union, add back an empty one.
        if is_root:
            parent_mform.add_subform('union', UnionMultiForm, data=None)
            LOG.debug('Adding root union back')
        return

    # Note that some of the n_children could be non-existent (i.e. deleted)
    for i in range(0, n_children):
        child_name = '%s%d' % (SUB_UNION_PREFIX, i)
        if not union_mform.has_subform_data(child_name, data):
            LOG.debug('Skipping over non-existent subform: %s %s' %
                      (union_mform, child_name))
            continue
        union_mform.add_subform(child_name, UnionMultiForm, data)
        LOG.debug('Instantiating subform: %s %s' % (union_mform, child_name))
        # The child may have grand-children
        fixup_union(union_mform, child_name, data)

    if mgmt_form.cleaned_data['add']:
        id = mgmt_form.new_form_id()
        child_name = '%s%d' % (SUB_UNION_PREFIX, id)
        union_mform.add_subform(child_name, UnionMultiForm)
        LOG.debug('Added subform: %s %s' % (union_mform, child_name))
示例#7
0
    def _make_selection(self, table_alias_dict, is_left):
        if is_left:
            prefix = 'l_'
        else:
            prefix = 'r_'

        source = self.cleaned_data[prefix + 'source']
        if source == 'table':
            table = self.cleaned_data[prefix + 'table']
            col = self.cleaned_data[prefix + 'col']
            try:
                return report_gen.ColumnSelection(table_alias_dict[table], col)
            except KeyError:
                raise forms.ValidationError('Unknown table "%s" in condition' %
                                            (table, ))

        constant = self.cleaned_data[prefix + 'constant']
        return report_gen.ConstSelection(constant)