예제 #1
0
    def check_key(self, attribute, temp_keys):
        is_super_key = False
        for key in temp_keys:
            if set(set(key.Attributes)).issubset(attribute):
                is_super_key = True
                break

        if not is_super_key:
            if set(self.compute_attribute_closure(self.FDs, attribute)) == set(self.Attributes):
                key = Key()
                key.Attributes = attribute[:]
                temp_keys.append(key)
예제 #2
0
    def compute_candidate_keys(self):
        temp_keys = []
        left = []           # contains attributes appear 'only' on the left hand sides of FDs
                            # 'left' attributes must be part of every key
        middle = []         # contains attributes appear on both left and right hand sides of FDs
                            # 'middle' attributes may or may not part of a key
        right = []          # contains attributes appear 'only' on the right hand sides of FDs
                            # 'right' attributes are not part of any key

        for fd in self.FDs:
            left += fd.leftHandSide
            right += fd.rightHandSide

        middle = list(set(left).intersection(set(right)))
        left = list(set(left)-set(middle))
        right = list(set(right)-set(middle))

        if len(left) > 0:
            # check keys in left list
            self.check_attribute_list(left, temp_keys)

            # if keys still not found, check keys in left list with middle list combinations
            if len(temp_keys) == 0:
                r1 = 1
                while r1 != (len(left)+1):
                    for left_combination in itertools.combinations(left, r1):
                        r2 = 1
                        while r2 != (len(middle)+1):
                            for middle_combination in itertools.combinations(middle, r2):
                                self.check_key(list(left_combination) + list(middle_combination), temp_keys)
                            #if len(temp_keys) > 0:
                            #    break
                            r2 += 1
                    #if len(temp_keys) > 0:
                    #        break
                    r1 += 1
        else:
            # check keys in middle list
            self.check_attribute_list(middle, temp_keys)

        if len(temp_keys) == 0:
            key = Key()
            # Basic Key U->U:
            key.Attributes = self.Attributes
            temp_keys.append(key)

        self.Keys = temp_keys[:]
예제 #3
0
    def decompose(self):
        if len(self.FdsViolateNF) > 0:
            nasty_fd = self.FdsViolateNF[0]

            lhs_closure = self.compute_attribute_closure(self.FDs, nasty_fd.leftHandSide)
            r1 = Relation()
            r1.Name = self.Name + "1"
            r1.Attributes = lhs_closure
            r1.compute_fds_from_original(self.canonical_cover)
            key = Key()
            key.Attributes = nasty_fd.leftHandSide
            r1.Keys.append(key)
            #r1.compute_candidate_keys()
            r1.computeNormalForm()
            r1.inherit_parent_foreign_keys(self.foreign_keys)
            self.decomposed_relations.append(r1)

            #if not (r1.NormalForm == '3NF' or r1.NormalForm == 'BCNF'):
            if r1.NormalForm != 'BCNF':
                r1.decompose()

            r2 = Relation()
            r2.Name = self.Name + "2"
            r2.Attributes = list(set(self.Attributes).difference(set(lhs_closure).difference(set(nasty_fd.leftHandSide))))
            r2.compute_fds_from_original(self.canonical_cover)
            r2.compute_candidate_keys()
            r2.computeNormalForm()
            r2.inherit_parent_foreign_keys(self.foreign_keys)
            r2.foreign_keys.append(ForeignKey(nasty_fd.leftHandSide, r1))

            self.decomposed_relations.append(r2)

            if r2.NormalForm != 'BCNF':
                r2.decompose()

            # here: ZT relation to preserve Z −> T
            remaining_fds = list((set(self.canonical_cover)-set(r1.FDs))-set(r2.FDs))
            if len(remaining_fds) > 0:
                index = 3
                for fd in remaining_fds:
                    if set(fd.leftHandSide + fd.rightHandSide) == set(self.Attributes):
                        self.FdsToDrop.append(fd)
                    else:
                        r = Relation()
                        r.Name = self.Name + str(index)
                        r.Attributes = fd.leftHandSide + fd.rightHandSide
                        r.FDs.append(fd)
                        r.compute_candidate_keys()
                        r.computeNormalForm()
                        self.decomposed_relations.append(r)

                        r.inherit_parent_foreign_keys(self.foreign_keys)

                        # Foreign Key computation:
                        for key in r1.Keys:
                            if key.Attributes == r.Attributes:
                                r.foreign_keys.append(ForeignKey(key.Attributes, r1))

                        for key in r2.Keys:
                            if key.Attributes == r.Attributes:
                                r.foreign_keys.append(ForeignKey(key.Attributes, r2))

                        if r.NormalForm != 'BCNF':
                            r.decompose()

                        index += 1