use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class QueryNode method removeEntityAttribute.
/**
* Sets updateable to true or false
*
* @param inUpdateable,
* true if we can update
* @author Federico Mora public void setUpdateable(boolean inUpdateable) {
* updateable = inUpdateable; }
*/
/**
* Removes an attribute from the list
*
* @param inAttribute
* The attribute to be removed
* @author Federico Mora
*/
@Override
public void removeEntityAttribute(final EntityAttribute<ViewFrame, ViewGraphModel, View, QueryNode, View_Edge> inAttribute) {
final SketchGraphModel model = _ourSketch.getGraphModel();
model.beginUpdate();
final int attPos = _entityAttributes.indexOf(inAttribute);
final int nodePos = getAttributeNode().getIndex(inAttribute);
_entityAttributes.remove(inAttribute);
getAttributeNode().remove(inAttribute);
_ourSketch.refresh();
_theModel.refresh();
_theModel.getFrame().getInfoTreeUI().refreshTree(this);
_theModel.getGraphModel().postEdit(new AbstractUndoableEdit() {
/**
*/
private static final long serialVersionUID = -3013106807521458129L;
@Override
public void undo() {
super.undo();
_entityAttributes.add(attPos, inAttribute);
getAttributeNode().insert(inAttribute, nodePos);
_ourSketch.refresh();
_theModel.refresh();
_theModel.getFrame().getInfoTreeUI().refreshTree(QueryNode.this);
}
@Override
public void redo() {
super.redo();
_entityAttributes.remove(inAttribute);
getAttributeNode().remove(inAttribute);
_theModel.refresh();
_theModel.refresh();
_theModel.getFrame().getInfoTreeUI().refreshTree(QueryNode.this);
}
});
/**
* might be needed if we unique keys
*
* // Remove references to the attribute from unique keys for (final
* UniqueKey curKey : _uniqueKeys) { curKey.removeElement(inAttribute);
* }
*
* // Fix up any empty/duplicate unique keys resulting from the
* attribute removal UniqueKey.cleanup(this);
*/
model.endUpdate();
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class MySQLExporter method createConstraint.
/**
* @param constraint
* @param id
*
* @return
*/
@Override
public List<String> createConstraint(final ProductConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> constraint, final String id) {
final List<String> sql = new LinkedList<>();
final String delConName = "productConstraint" + id + "Delete";
StringBuilder proc = new StringBuilder(500);
proc.append("CREATE PROCEDURE ").append(quoteId(delConName)).append("(id ").append(pkType()).append(") BEGIN").append(lineSep);
EntityNode begin = null;
int j = 0;
// c.b_id = b.id JOIN d ON d.c_id = c.id...> WHERE <begin> = id;
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> p : constraint.getPaths()) {
if (begin == null) {
begin = p.getDomain();
}
proc.append(" DELETE ").append(quoteId(p.getCoDomain())).append(" FROM ").append(joinPath(p)).append(lineSep).append(" WHERE ").append(qualifiedPK(begin)).append(" = id;").append(lineSep);
// Federico Mora
StringBuilder proc1 = new StringBuilder(500);
StringBuilder body = new StringBuilder(50);
proc1.append("CREATE PROCEDURE ").append("Update" + constraint.getID() + "Proj" + j++).append("() BEGIN").append(lineSep);
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> q : constraint.getPaths()) {
if (p == q) {
// do nothing, cascade will take care of it
} else {
// making the update string which is used by all the delete
// procedures.
final LinkedList<SketchEdge> edges = q.getEdges();
if (edges.size() >= 2) {
Iterator<SketchEdge> iter = edges.iterator();
SketchEdge e = iter.next();
body.append(" UPDATE ").append(leftJoinPath(q)).append(lineSep);
body.append(" SET");
while (iter.hasNext()) {
SketchEdge ske = iter.next();
body.append(" " + quoteId(ske.getSourceEntity()) + ".BC" + constraint.getID() + " = " + false + ",");
}
body.delete(body.length() - 1, body.length());
body.append(" WHERE " + qualifiedFK(e) + " IS NULL;" + lineSep);
}
}
}
if (body.length() > 0) {
proc1.append(body);
proc1.append("END");
sql.add(proc1.toString());
// Now create the triggers to call the new procedure
addTrigger(p.getCoDomain(), "AFTER DELETE", "CALL " + quoteId("Update" + constraint.getID() + "Proj" + (j - 1)) + "()");
}
// end Federico Mora
}
// Select B.id From A Join B On A.f1 = B.id Join D On A.f3 = D.id Where
// D.id = 1
proc.append("END");
sql.add(proc.toString());
// Now create the trigger to call the new procedure
addTrigger(begin, "BEFORE DELETE", "CALL " + quoteId(delConName) + "(OLD." + quoteId(tablePK(begin)) + ')');
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> p : constraint.getPaths()) {
final EntityNode dest = p.getCoDomain();
final String conName = "productConstraint" + id + "Insert" + cleanId(dest);
final Collection<String> args = new LinkedList<>();
final Collection<String> params = new LinkedList<>();
args.add("id " + pkType());
params.add("NEW." + quoteId(tablePK(dest)));
// commented out by Sarah van der Laan -- caused error in generated
// SQL file (invalid foreign keys)
/**
* for (final SketchEdge shadow : dest.getShadowEdges()) {
* args.add(quoteId("NEW_shadow_" + tableFK(shadow)) + ' ' +
* pkType()); params.add("NEW." + quoteId(tableFK(shadow))); }
*/
proc = new StringBuilder(500);
proc.append("CREATE PROCEDURE ").append(quoteId(conName)).append('(').append(EasikTools.join(", ", args)).append(") BEGIN").append(lineSep).append(" DECLARE _lastId ").append(pkType()).append(';').append(lineSep);
final StringBuilder createIntermediates = new StringBuilder(250);
final Collection<String> clauses = new LinkedList<>();
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> q : constraint.getPaths()) {
if (p == q) {
continue;
}
// Older versions were doing "SELECT COUNT(*) FROM TABLE", but
// that has a big
// performance hit for very large, busy InnoDB tables, when all
// we really care
// about is non-empty:
clauses.add("(SELECT 1 FROM " + quoteId(q.getCoDomain()) + " LIMIT 1) = 1");
// If we end up putting anything in createIntermediate, we'll
// use these
// insertions when we insert the first row into one of the path
// targets
final LinkedList<SketchEdge> sketchEdgeLinkedList = q.getEdges();
final SketchEdge[] edges = sketchEdgeLinkedList.toArray(new SketchEdge[sketchEdgeLinkedList.size()]);
for (int i = edges.length - 1; i > 0; i--) {
final SketchEdge e = edges[i];
final EntityNode source = e.getSourceEntity();
final EntityNode target = e.getTargetEntity();
// after source there used to be dest.getShadowEdges();
createIntermediates.append(" ").append(insertInto(true, source, qualifiedPK(target), quoteId(target), Collections.singletonList(quoteId(tableFK(e))), null));
}
}
// In words: If the tables forming the domains of the other paths
// contain items.
proc.append(" IF ").append(EasikTools.join(" AND ", clauses)).append(" THEN").append(lineSep);
if (createIntermediates.length() > 0) {
// If we just inserted the first row, we're going to have to
// build a path of intermediate tables
// for the other paths, which we built in createIntermediate.
proc.append(" IF (SELECT COUNT(*) FROM (SELECT 1 FROM ").append(quoteId(dest)).append(" LIMIT 2) a) = 1 THEN").append(lineSep).append(createIntermediates).append(" END IF;").append(lineSep).append("").append(lineSep);
}
// Produce the intermediate path insertion strings
final LinkedList<SketchEdge> sketchEdgeLinkedList = p.getEdges();
final SketchEdge[] edges = sketchEdgeLinkedList.toArray(new SketchEdge[sketchEdgeLinkedList.size()]);
if (edges.length > 1) {
for (int i = edges.length - 1; i > 0; i--) {
final SketchEdge e = edges[i];
final EntityNode source = e.getSourceEntity();
@SuppressWarnings("unused") final EntityNode target = e.getTargetEntity();
// after source there used to be dest.getShadowEdges();
proc.append(" ").append(insertInto(true, source, null, null, Collections.singletonList(quoteId(tableFK(e))), Collections.singletonList((i == edges.length - 1) ? "id" : "LAST_INSERT_ID()")));
}
proc.append(" SET _lastId = LAST_INSERT_ID();").append(lineSep);
} else {
proc.append(" SET _lastId = id;").append(lineSep);
}
// Now the proper insertion
final List<String> columns = new LinkedList<>();
final Collection<String> values = new LinkedList<>();
final Collection<String> from = new LinkedList<>();
EntityNode thisTarget = null;
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> q : constraint.getPaths()) {
final EntityNode target = q.getFirstEdge().getTargetEntity();
columns.add(quoteId(tableFK(q.getFirstEdge())));
values.add(qualifiedPK(target));
from.add(quoteId(target));
if (q == p) {
thisTarget = target;
}
}
// after begin there used to be dest.getShadowEdges();
proc.append(" ").append(insertInto(true, begin, EasikTools.join(", ", values), EasikTools.join(" CROSS JOIN ", from) + " WHERE " + qualifiedPK(thisTarget) + " = _lastId", columns, null)).append(" END IF;").append(lineSep).append("END");
sql.add(proc.toString());
addTrigger(dest, "AFTER INSERT", "CALL " + quoteId(conName) + '(' + EasikTools.join(", ", params) + ')');
}
return delimit("$$", sql);
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class MySQLExporter method createConstraint.
/**
* @param constraint
* @param id
*
* @return
*/
@Override
public List<String> createConstraint(final SumConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> constraint, final String id) {
final List<String> sql = new LinkedList<>();
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> path : constraint.getPaths()) {
final EntityNode dom = path.getDomain();
final EntityNode codo = path.getCoDomain();
final String baseConName = "sumConstraint" + id + cleanId(dom);
final StringBuilder proc = new StringBuilder(500);
proc.append("CREATE PROCEDURE ").append(quoteId(baseConName + "Delete")).append("(_deleteFK ").append(pkType()).append(") BEGIN").append(lineSep).append(" DELETE FROM ").append(quoteId(codo)).append(" WHERE ").append(qualifiedPK(codo)).append(" = ");
if (path.getEdges().size() == 1) {
proc.append("_deleteFK");
} else {
final LinkedList<SketchEdge> trailing = new LinkedList<>(path.getEdges());
trailing.removeFirst();
proc.append("(SELECT ").append(qualifiedFK(trailing.getLast())).append(" FROM ").append(joinPath(trailing, false)).append(" WHERE ").append(qualifiedPK(path.getFirstCoDomain())).append(" = _deleteFK)");
}
proc.append(';').append(lineSep).append("END");
sql.add(proc.toString());
addTrigger(dom, "AFTER DELETE", "CALL " + quoteId(baseConName + "Delete") + "(OLD." + quoteId(tableFK(path.getFirstEdge())) + ')');
final List<String> insertions = new LinkedList<>();
// after codo there used to be dest.getShadowEdges();
insertions.add(insertInto(false, codo, null, null, null, null));
final SketchEdge[] edges = path.getEdges().toArray(new SketchEdge[path.getEdges().size()]);
for (int i = edges.length - 1; i > 0; i--) {
final EntityNode source = edges[i].getSourceEntity();
// after source there used to be dest.getShadowEdges();
insertions.add(insertInto(false, source, null, null, Collections.singletonList(quoteId(tableFK(edges[i]))), Collections.singletonList("LAST_INSERT_ID()")));
}
insertions.add("SET NEW." + quoteId(tableFK(edges[0])) + " = LAST_INSERT_ID()");
addTrigger(dom, "BEFORE INSERT", insertions);
}
return delimit("$$", sql);
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class MySQLExporter method createConstraint.
/**
* @param cd
* @param id
*
* @return
*/
@Override
public List<String> createConstraint(final CommutativeDiagram<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> cd, final String id) {
final List<String> sql = new LinkedList<>();
final List<ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>> paths = cd.getPaths();
final EntityNode dom = paths.get(0).getDomain();
final StringBuilder proc = new StringBuilder("");
final List<String> declarations = new LinkedList<>();
final List<String> values = new LinkedList<>();
final List<String> args = new LinkedList<>();
final List<String> params = new LinkedList<>();
int targetNum = 0;
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> path : paths) {
++targetNum;
final LinkedList<SketchEdge> tmpPath = new LinkedList<>(path.getEdges());
tmpPath.removeFirst();
final String fk = "_path" + targetNum + "fk";
args.add(fk + ' ' + pkType());
params.add("NEW." + quoteId(tableFK(path.getFirstEdge())));
declarations.add("_cdTarget" + targetNum);
if (tmpPath.size() == 0) {
values.add(" SELECT " + fk + " INTO _cdTarget" + targetNum + ';' + lineSep);
} else {
values.add(" SELECT " + qualifiedFK(path.getLastEdge()) + " INTO _cdTarget" + targetNum + " FROM " + joinPath(tmpPath, false) + " WHERE " + qualifiedPK(tmpPath.getFirst().getSourceEntity()) + " = " + fk + ';' + lineSep);
}
}
proc.append("CREATE PROCEDURE ").append(quoteId("commutativeDiagram" + id)).append('(').append(EasikTools.join(", ", args)).append(") BEGIN").append(lineSep).append(" DECLARE ").append(EasikTools.join(", ", declarations)).append(' ').append(pkType()).append(';').append(lineSep).append(EasikTools.join("", values)).append(" IF").append(lineSep);
for (int i = 2; i <= targetNum; i++) {
proc.append(" NOT (_cdTarget1 <=> _cdTarget").append(i).append(')');
if (i < targetNum) {
proc.append(" OR");
}
proc.append(lineSep);
}
proc.append(" THEN CALL constraint_failure('Commutative diagram constraint failure.');").append(lineSep).append(" END IF;").append(lineSep).append("END");
addFail = true;
sql.addAll(delimit("$$", proc));
addTrigger(dom, "BEFORE INSERT", "CALL " + quoteId("commutativeDiagram" + id) + '(' + EasikTools.join(", ", params) + ')');
return sql;
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class MySQLExporter method createConstraint.
/**
* @param constraint
* @param id
*
* @return
*/
@Override
public List<String> createConstraint(final EqualizerConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> constraint, final String id) {
final List<String> sql = new LinkedList<>();
final EntityNode eq = constraint.getEqualizerEntity();
final EntityNode source = constraint.getSourceEntity();
final EntityNode target = constraint.getTargetEntity();
final InjectiveEdge projEdge = (InjectiveEdge) constraint.getProjection().getFirstEdge();
final List<ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>> paths = constraint.getEqualizerPaths();
final String insConName = "eqCon" + id + "InsUpd" + cleanId(source);
final Collection<String> args = new LinkedList<>();
final Collection<String> params = new LinkedList<>();
args.add("_newId " + pkType());
params.add("NEW." + quoteId(tablePK(source)));
// commented out by Sarah van der Laan -- caused error in generated SQL
// file (invalid foreign keys)
/**
* for (final SketchEdge shadow : source.getShadowEdges()) {
* args.add(quoteId("NEW_shadow_" + tableFK(shadow)) + ' ' + pkType());
* params.add("NEW." + quoteId(tableFK(shadow))); }
*/
final StringBuilder proc = new StringBuilder(500);
proc.append("CREATE PROCEDURE ").append(quoteId(insConName)).append('(').append(EasikTools.join(", ", args)).append(") BEGIN").append(lineSep);
proc.append(" DECLARE _path0Id");
// Add a variable for each path, _path0Id, _path1Id, etc.:
for (int i = 1; i < paths.size(); i++) {
proc.append(", _path").append(i).append("Id");
}
proc.append(' ').append(pkType()).append(';').append(lineSep);
final String sourcePK = qualifiedPK(source);
final String targetPK = qualifiedPK(target);
final String newPK = "_newId";
int i = 0;
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> p : paths) {
proc.append(" SELECT ").append(targetPK).append(" INTO _path").append(i).append("Id").append(lineSep).append(" FROM ").append(joinPath(p)).append(lineSep).append(" WHERE ").append(sourcePK).append(" = ").append(newPK).append(';').append(lineSep);
++i;
}
// Build equality clause, such as: _path0Id IS DISTINCT FROM _path1Id OR
// _path0Id IS DISTINCT FROM _path2Id OR ...
proc.append(" IF NOT (_path0Id <=> _path1Id)");
for (int j = 2; j < paths.size(); j++) {
proc.append(" OR NOT (_path0Id <=> _path").append(j).append("Id)");
}
proc.append(" THEN").append(lineSep).append(// delete it from the equalizer (if it's there)
" DELETE FROM ").append(quoteId(eq)).append(" WHERE ").append(qualifiedFK(projEdge)).append(" = ").append(newPK).append(';').append(lineSep).append(" ELSEIF (SELECT COUNT(*) FROM ").append(quoteId(eq)).append(" WHERE ").append(qualifiedFK(projEdge)).append(" = ").append(newPK).append(") = 0 THEN").append(lineSep).append(// add it:
" ");
/*
* Deal with intermediate nodes in projection Federico Mora
*/
ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> path = constraint.getProjection();
final SketchEdge[] edges = path.getEdges().toArray(new SketchEdge[path.getEdges().size()]);
for (int j = edges.length - 1; j > 0; j--) {
final EntityNode s = edges[j].getSourceEntity();
if (j == edges.length - 1) {
// after s there used to be dest.getShadowEdges();
proc.append(insertInto(false, s, null, null, Collections.singletonList(quoteId(tableFK(edges[j]))), Collections.singletonList("_newId")));
} else {
// after source there used to be dest.getShadowEdges();
proc.append(insertInto(false, s, null, null, Collections.singletonList(quoteId(tableFK(edges[j]))), Collections.singletonList("LAST_INSERT_ID()")));
}
}
// done - deal with intermediate nodes in projection
// after eq there used to be dest.getShadowEdges();
proc.append(" ").append(insertInto(true, eq, null, null, Collections.singletonList(quoteId(tableFK(projEdge))), Collections.singletonList("LAST_INSERT_ID()"))).append(" END IF;").append(lineSep).append("END").append(lineSep);
sql.add(proc.toString());
// Create the trigger for inserting into the source table:
final String call = "CALL " + quoteId(insConName) + '(' + EasikTools.join(", ", params) + ')';
addTrigger(source, "AFTER INSERT", call);
addTrigger(source, "AFTER UPDATE", call);
// If the projection isn't a cascading edge, cascade:
if (projEdge.getCascading() != SketchEdge.Cascade.CASCADE) {
addTrigger(source, "BEFORE DELETE", "DELETE FROM " + quoteId(eq) + " WHERE " + qualifiedFK(projEdge) + " = OLD." + quoteId(tablePK(source)));
}
// Federico Mora
ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> p = constraint.getProjection();
StringBuilder proc1 = new StringBuilder(500);
proc1.append("CREATE PROCEDURE ").append("Update" + constraint.getID() + "Proj").append("() BEGIN").append(lineSep);
// making the update string which is used by all the delete
// procedures.
final LinkedList<SketchEdge> egs = p.getEdges();
if (egs.size() >= 2) {
Iterator<SketchEdge> iter = egs.iterator();
SketchEdge e = iter.next();
proc1.append(" UPDATE ").append(leftJoinPath(p)).append(lineSep);
proc1.append(" SET");
while (iter.hasNext()) {
SketchEdge ske = iter.next();
proc1.append(" " + quoteId(ske.getSourceEntity()) + ".BC" + constraint.getID() + " = " + false + ",");
}
proc1.delete(proc1.length() - 1, proc1.length());
proc1.append(" WHERE " + qualifiedFK(e) + " IS NULL;" + lineSep);
proc1.append("END");
sql.add(proc1.toString());
// Now create the triggers to call the new procedure
addTrigger(p.getCoDomain(), "AFTER UPDATE", "CALL " + quoteId("Update" + constraint.getID() + "Proj") + "()");
}
return delimit("$$", sql);
}
Aggregations