예제 #1
0
    /// <summary>
    /// Μέθοδος στην οποία γίνεται η επιλεγμένη διάσπαση.
    /// </summary>
    /// <param name="isPreview">Αν είναι αληθής τότε εμφανίζονται στο modal τα αποτελέσματα.</param>
    private void DecomposeInSteps(bool isPreview)
    {
        int iRel = 0;
        int iFD  = 0;

        UpdateExcludedFD();

        // προσδιορίζεται ο πίνακας που έχει επιλεγεί.
        Relation rel = null;

        iRel = Int32.Parse(gridViewRelationHiddenField.Value);
        rel  = relList[iRel];

        // αν ο πίνακας που έχει επιλεγεί δεν μπορεί να διασπαστεί περαιτέρω, βγαίνει σχετικό μήνυμα.
        if (!isPreview && rel.Excluded)
        {
            log.InnerText = "Ο πίνακας\n\n" + rel.ToString() + "\n\nέχει αποκλειστεί από περαιτέρω διασπάσεις.";
            return;
        }

        // προσδιορίζεται η συναρτησιακή εξάρτηση που έχει επιλεγεί.
        FD fd = null;

        iFD = Int32.Parse(gridViewFDHiddenField.Value);
        fd  = fdList[iFD];

        // εξετάζεται αν η συναρτησιακή εξάρτηση είναι τετριμμένη.
        if (fd.IsTrivial)
        {
            log.InnerText = "Η συναρτησιακή εξάρτηση\n\n\"" + fd.ToString() + "\"\n\nείναι τετριμμένη, επομένως δεν χρησιμοποιείται για διάσπαση πινάκων.";
            return;
        }

        //αν το αριστερό σκέλος της συναρτησιακής εξάρτησης περιλαμβάνει κλειδί, τότε δεν χρησιμοποιείται
        //ο έλεγχος γίνεται με τη βοήθεια της τομής.
        foreach (Key key in keyList)
        {
            if (fd.GetLeft().Intersect(key.GetAttrs(), Global.comparer).Count() >= key.GetAttrs().Count)
            {
                log.InnerText = "Η συναρτησιακή εξάρτηση\n\n\"" + fd.ToString() + "\"\n\nπεριλαμβάνει υποψήφιο κλειδί στο αριστερό σκέλος της, επομένως δεν παραβιάζει την BCNF μορφή και δεν χρησιμοποιείται για διάσπαση πινάκων.";
                return;
            }
        }

        // επίσης ελέγχεται αν η συναρτησιακή εξάρτηση έχει ως ορίζουσα υποψήφιο κλειδί του προς διάσπαση πίνακα.
        List <Key> tempoRelKey = new List <Key>();
        var        resultTemp  = Global.findKeys(rel.GetList(), fdList, false);

        tempoRelKey = resultTemp.Item1;

        foreach (Key key in tempoRelKey)
        {
            if (fd.GetLeft().Intersect(key.GetAttrs(), Global.comparer).Count() >= key.GetAttrs().Count)
            {
                log.InnerText = "Η συναρτησιακή εξάρτηση\n\n\"" + fd.ToString() + "\"\n\nπεριλαμβάνει υποψήφιο κλειδί του πίνακα " + rel.Name + ", επομένως δεν μπορεί να τον διασπάσει.";
                return;
            }
        }

        // αν η τομή x του συνόλου των γνωρισμάτων της συναρτησιακής εξάρτησης και των γνωρισμάτων του πίνακα είναι μικρότερη σε αριθμό από το πλήθος των γνωρισμάτων του πίνακα και ίση με το πλήθος των γνωρισμάτων της συναρτησιακής εξάρτησης, τότε παραβιάζεται η BCNF μορφή και ο πίνακας μπορεί να διασπαστεί.
        int x = fd.GetAll().Intersect(rel.GetList(), Global.comparer).Count();

        if (x < rel.GetList().Count&& x == fd.GetAll().Count)
        {
            // παρακάτω δημιουργούνται δύο νέοι πίνακες, ο rel1 και ο rel2.

            // ο rel1 πίνακας παίρνει τα γνωρίσματα της συναρτησιακής εξάρτησης.
            Relation rel1 = new Relation(fd.GetAll());

            // ο rel2 πίνακας παίρνει τα γνωρίσματα από το αριστερό σκέλος της συναρτησιακής εξάρτησης, συν τα γνωρίσματα του πίνακα που διασπάστηκε, πλην αυτών που βρίσκονται στο δεξί σκέλος της συναρτησιακής εξάρτησης.
            List <Attr> tempo = new List <Attr>();
            tempo.AddRange(fd.GetLeft());
            tempo.AddRange(rel.GetList().Except(fd.GetRight(), Global.comparer));
            Relation rel2 = new Relation(tempo);

            // δημιουργούνται δύο κλειδιά, ένα για τον καθένα πίνακα.
            Key key1 = new Key();
            Key key2 = new Key();

            // το κλειδί του πρώτου πίνακα είναι η ορίζουσα της συναρτησιακής εξάρτησης που προκάλεσε την διάσπαση.
            key1.AddToKey(fd.GetLeft());
            rel1.SetKey(key1);

            // προσδιορίζουμε το κλειδί του δεύτερου πίνακα (αυτό που δίνει όλα τα γνωρίσματά του)
            // δημιουργούμε μια τοπική λίστα κλειδιών και ως κλειδί του δεύτερου πίνακα ορίζεται το πρώτο κλειδί της λίστας.
            List <Key> tempoKeyList = new List <Key>();
            var        resultTemp2  = Global.findKeys(rel2.GetList(), fdList, false);
            tempoKeyList = resultTemp2.Item1;

            key2.AddToKey(tempoKeyList[0].GetAttrs());
            rel2.SetKey(key2);

            // ορίζονται τα ονόματα των δύο νέων πινάκων.
            if (Relation.isAA)
            {
                rel1.Name = "R" + ++Relation.aa;
                rel2.Name = "R" + ++Relation.aa;
                if (isPreview)
                {
                    Relation.aa = Relation.aa - 2;
                }
            }
            else
            {
                rel1.Name = rel.Name + "1";
                rel2.Name = rel.Name + "2";
            }

            // οι δύο νέοι πίνακες προστίθενται στη λίστα.
            if (!isPreview)
            {
                //προστίθενται οι δύο νέοι πίνακας στο CheckboxList
                relList.Add(rel1);
                relList.Add(rel2);

                //εμφανίζονται τα σχετικά μηνύματα στα Αποτελέσματα.
                resultsArea.InnerText += "\nΜε την \"" + fd.ToString() + "\" ο " + rel.Name + " διασπάται σε:\n\n" + rel1.ToString() + RelBCNF(rel1) + "\n\n" + rel2.ToString() + RelBCNF(rel2) + "\n\n";
                resultsArea.InnerText += "==============================\n\n";


                //μπαίνει Χ στα Grid για τον πίνακα rel και τη συναρτησιακή εξάρτηση fd
                rel.IsBCNF           = false;
                rel.Excluded         = true;
                fdList[iFD].Excluded = true;

                log.InnerText = "Έγινε διάσπαση σε δύο νέους πίνακες, τον " + rel1.Name + " και τον " + rel2.Name + ".";
            }
            else
            {
                log.InnerText  = "Με την \"" + fd.ToString() + "\" ο " + rel.ToString() + " διασπάται σε:\n\n" + rel1.ToString() + RelBCNF(rel1) + "\n\n" + rel2.ToString() + RelBCNF(rel2) + "\n\n";
                log.InnerText += "==============================\n\n";
            }
        }
        else // σε διαφορετική περίπτωση η BCNF δεν παραβιάζεται και εμφανίζεται σχετικό μήνυμα
        {
            log.InnerText = "Η συναρτησιακή εξάρτηση\n\n\"" + fd.ToString() + "\"\n\nδεν σχετίζεται με τον πίνακα\n\n" + rel.ToString() + "\n\nκαι επομένως δεν γίνεται διάσπαση.";
        }
    }