OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 73 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 73 Rev 132
Line 15... Line 15...
15
 
15
 
16
import org.openconcerto.sql.Configuration;
16
import org.openconcerto.sql.Configuration;
17
import org.openconcerto.sql.changer.Changer;
17
import org.openconcerto.sql.changer.Changer;
18
import org.openconcerto.sql.element.SQLElement;
18
import org.openconcerto.sql.element.SQLElement;
19
import org.openconcerto.sql.element.SQLElementDirectory;
19
import org.openconcerto.sql.element.SQLElementDirectory;
-
 
20
import org.openconcerto.sql.element.SQLElementLink;
-
 
21
import org.openconcerto.sql.element.SQLElementLink.LinkType;
20
import org.openconcerto.sql.model.DBSystemRoot;
22
import org.openconcerto.sql.model.DBSystemRoot;
21
import org.openconcerto.sql.model.SQLField;
23
import org.openconcerto.sql.model.SQLField;
22
import org.openconcerto.sql.model.SQLRow;
-
 
23
import org.openconcerto.sql.model.SQLRowListRSH;
-
 
24
import org.openconcerto.sql.model.SQLRowValues;
24
import org.openconcerto.sql.model.SQLRowValues;
-
 
25
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
25
import org.openconcerto.sql.model.SQLSelect;
26
import org.openconcerto.sql.model.SQLSelect;
26
import org.openconcerto.sql.model.SQLSelect.ArchiveMode;
27
import org.openconcerto.sql.model.SQLSelect.ArchiveMode;
27
import org.openconcerto.sql.model.SQLTable;
28
import org.openconcerto.sql.model.SQLTable;
28
import org.openconcerto.sql.model.Where;
29
import org.openconcerto.sql.model.Where;
-
 
30
import org.openconcerto.sql.model.graph.Path;
-
 
31
import org.openconcerto.sql.model.graph.Step;
29
import org.openconcerto.sql.utils.SQLUtils;
32
import org.openconcerto.sql.utils.SQLUtils;
30
import org.openconcerto.sql.utils.SQLUtils.SQLFactory;
33
import org.openconcerto.sql.utils.SQLUtils.SQLFactory;
-
 
34
import org.openconcerto.utils.cc.ITransformer;
31
 
35
 
32
import java.sql.SQLException;
36
import java.sql.SQLException;
33
import java.util.List;
37
import java.util.List;
34
 
38
 
35
/**
39
/**
Line 74... Line 78...
74
            return;
78
            return;
75
        } else {
79
        } else {
76
            getStream().println("... ");
80
            getStream().println("... ");
77
        }
81
        }
78
 
82
 
-
 
83
        for (final SQLElementLink elemLink : elem.getOwnedLinks().getByType(LinkType.COMPOSITION)) {
-
 
84
            // e.g. to either MISSION (i.e. empty path) or MISSION_Q18
-
 
85
            final Path pathToForeign = elemLink.getPath().minusLast();
-
 
86
            // e.g. ID_Q18
79
        for (final String pff : elem.getPrivateForeignFields()) {
87
            final Step toPrivateStep = elemLink.getPath().getStep(-1);
-
 
88
 
80
            // eg Q18
89
            // eg Q18
81
            final SQLElement privateElement = elem.getPrivateElement(pff);
90
            final SQLElement privateElement = elemLink.getOwned();
82
            final SQLTable privateTable = privateElement.getTable();
91
            final SQLTable privateTable = privateElement.getTable();
83
            // SELECT q.ID FROM Ideation_2007.Q18 q
92
            // SELECT q.ID FROM Ideation_2007.Q18 q
84
            // JOIN Ideation_2007.MISSION m on m.ID_Q18 = q.ID
93
            // JOIN Ideation_2007.MISSION m on m.ID_Q18 = q.ID
85
            // where q.ID != 1
94
            // where q.ID != 1
86
            // GROUP BY q.ID
95
            // GROUP BY q.ID
87
            // HAVING count(q.ID) > 1;
96
            // HAVING count(q.ID) > 1;
88
            final SQLSelect sel = new SQLSelect();
97
            final SQLSelect sel = new SQLSelect();
89
            sel.setArchivedPolicy(ArchiveMode.BOTH);
98
            sel.setArchivedPolicy(ArchiveMode.BOTH);
90
            sel.addSelect(privateTable.getKey());
99
            sel.addSelect(privateTable.getKey());
-
 
100
            // The last step of a ElementLink is always foreign, be it a simple foreign key or with
-
 
101
            // a join table. Thus we don't need to go back to the main row to find duplicates.
-
 
102
            assert toPrivateStep.isForeign();
91
            sel.addBackwardJoin("INNER", "m", t.getField(pff), null);
103
            sel.addJoin("INNER", null, toPrivateStep.reverse(), "m");
92
            final String req = sel.asString() + " GROUP BY " + privateTable.getKey().getFieldRef() + " HAVING count(" + privateTable.getKey().getFieldRef() + ")>1";
104
            final String req = sel.asString() + " GROUP BY " + privateTable.getKey().getFieldRef() + " HAVING count(" + privateTable.getKey().getFieldRef() + ")>1";
93
 
105
 
94
            @SuppressWarnings("unchecked")
106
            @SuppressWarnings("unchecked")
95
            final List<Number> privateIDs = t.getDBSystemRoot().getDataSource().executeCol(req);
107
            final List<Number> privateIDs = t.getDBSystemRoot().getDataSource().executeCol(req);
96
            if (privateIDs.size() > 0) {
108
            if (privateIDs.size() > 0) {
97
                getStream().println("\t" + pff + " fixing " + privateIDs.size() + " ... ");
109
                getStream().println("\t" + elemLink + " fixing " + privateIDs.size() + " ... ");
98
                final SQLField archF = t.getArchiveField();
110
                final SQLField archF = t.getArchiveField();
99
                final SQLField privateArchF = privateTable.getArchiveField();
111
                final SQLField privateArchF = privateTable.getArchiveField();
100
                if ((archF == null) != (privateArchF == null))
112
                if ((archF == null) != (privateArchF == null))
101
                    throw new IllegalStateException("Incoherent archive field : " + archF + " / " + privateArchF);
113
                    throw new IllegalStateException("Incoherent archive field : " + archF + " / " + privateArchF);
102
                SQLUtils.executeAtomic(t.getDBSystemRoot().getDataSource(), new SQLFactory<Object>() {
114
                SQLUtils.executeAtomic(t.getDBSystemRoot().getDataSource(), new SQLFactory<Object>() {
103
                    @Override
115
                    @Override
104
                    public Object create() throws SQLException {
116
                    public Object create() throws SQLException {
105
                        // for each private pointed by more than one parent
117
                        // for each private pointed by more than one parent
106
                        for (final Number privateID : privateIDs) {
118
                        for (final Number privateID : privateIDs) {
107
                            final SQLSelect fixSel = new SQLSelect();
119
                            final SQLRowValues vals = new SQLRowValues(t);
108
                            fixSel.setArchivedPolicy(ArchiveMode.BOTH);
-
 
109
                            fixSel.addSelect(t.getKey());
-
 
110
                            if (archF != null)
120
                            if (archF != null)
111
                                fixSel.addSelect(archF);
121
                                vals.putNulls(archF.getName());
-
 
122
                            // e.g. ID_OBSERVATION
-
 
123
                            final SQLField ff = toPrivateStep.getSingleField();
-
 
124
                            vals.assurePath(pathToForeign).putNulls(ff.getName());
-
 
125
 
-
 
126
                            final SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(vals);
-
 
127
                            fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
-
 
128
                                @Override
-
 
129
                                public SQLSelect transformChecked(SQLSelect fixSel) {
-
 
130
                                    fixSel.setArchivedPolicy(ArchiveMode.BOTH);
112
                            fixSel.setWhere(new Where(t.getField(pff), "=", privateID));
131
                                    fixSel.setWhere(new Where(fixSel.getAlias(ff), "=", privateID));
-
 
132
                                    return fixSel;
-
 
133
                                }
-
 
134
                            });
-
 
135
 
113
                            final List<SQLRow> tIDs = SQLRowListRSH.execute(fixSel);
136
                            final List<SQLRowValues> tIDs = fetcher.fetch();
114
                            for (final SQLRow tID : tIDs) {
137
                            for (final SQLRowValues tID : tIDs) {
115
                                // the first one can keep its private
138
                                // the first one can keep its private
116
                                final SQLRowValues reallyPrivate;
139
                                final SQLRowValues reallyPrivate;
117
                                if (tID == tIDs.get(0))
140
                                if (tID == tIDs.get(0))
118
                                    reallyPrivate = new SQLRowValues(privateElement.getTable()).setID(privateID);
141
                                    reallyPrivate = new SQLRowValues(privateElement.getTable()).setID(privateID);
119
                                else
142
                                else
120
                                    reallyPrivate = privateElement.createCopy(privateID.intValue());
143
                                    reallyPrivate = privateElement.createCopy(privateID.intValue());
121
                                // keep archive coherence
144
                                // keep archive coherence
122
                                if (archF != null)
145
                                if (archF != null)
123
                                    reallyPrivate.put(privateArchF.getName(), tID.getObject(archF.getName()));
146
                                    reallyPrivate.put(privateArchF.getName(), tID.getObject(archF.getName()));
124
                                new SQLRowValues(t).setID(tID.getIDNumber()).put(pff, reallyPrivate).update();
147
                                new SQLRowValues(pathToForeign.getLast()).setID(tID.followPath(pathToForeign).getIDNumber()).put(ff.getName(), reallyPrivate).update();
125
                            }
148
                            }
126
                        }
149
                        }
127
                        return null;
150
                        return null;
128
                    }
151
                    }
129
                });
152
                });