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 |
});
|