Search in sources :

Example 16 with EntityNode

use of easik.sketch.vertex.EntityNode in project fql by CategoricalData.

the class MySQLExporter method createConstraint.

/**
 * @param constraint
 * @param id
 *
 * @return
 */
@Override
public List<String> createConstraint(final PullbackConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> constraint, final String id) {
    final List<String> sql = new LinkedList<>();
    String tmpS = null;
    // Create the trigger for inserting into the pullback table:
    final EntityNode pb = constraint.getSource();
    final EntityNode target = constraint.getTarget();
    final String BASE_PATH_NAME = "_pathId";
    final int constraintWidth = constraint.getWidth();
    final String insConName = "pullbackConstraint" + id + "Insert" + cleanId(pb);
    StringBuilder proc = new StringBuilder(500);
    proc.append("CREATE PROCEDURE ");
    proc.append(quoteId(insConName));
    proc.append("(_newPBid ");
    proc.append(pkType());
    proc.append(") BEGIN");
    proc.append(lineSep);
    proc.append("   DECLARE ");
    for (int i = 0; i < constraintWidth; i++) {
        proc.append(BASE_PATH_NAME);
        proc.append(i);
        if (i != constraintWidth - 1) {
            proc.append(", ");
        } else {
            proc.append(" ");
        }
    }
    proc.append(pkType()).append(';').append(lineSep);
    final String basePK = qualifiedPK(pb);
    final String targetPK = qualifiedPK(target);
    for (int i = 0; i < constraintWidth; i++) {
        proc.append("       SELECT ").append(targetPK).append(" INTO " + BASE_PATH_NAME + i).append(lineSep).append("           FROM ").append(joinPath(constraint.getFullPath(i))).append(lineSep).append("           WHERE ").append(basePK).append(" = _newPBid;").append(lineSep);
    }
    // Make sure the paths match
    proc.append("   IF NOT");
    for (int i = 1; i < constraintWidth; i++) {
        proc.append(" (" + BASE_PATH_NAME + (i - 1) + " <=> " + BASE_PATH_NAME + i + ')');
        if (i != constraintWidth - 1) {
            proc.append(" OR NOT");
        }
    }
    proc.append(" THEN").append(lineSep).append("               CALL constraint_failure('Invalid entry in pullback constraint.');").append(lineSep).append("       END IF;").append(lineSep);
    addFail = true;
    final String pbQ = quoteId(pb);
    SketchEdge[] firstEdges = new SketchEdge[constraintWidth];
    for (int i = 0; i < constraintWidth; i++) {
        firstEdges[i] = constraint.getFullPath(i).getFirstEdge();
    }
    if (!addedUnique.isUnique(pb, firstEdges)) {
        tmpS = "ALTER TABLE " + pbQ + " ADD UNIQUE " + quoteId("pullbackConstraint" + id + "UniqueIndex") + " (";
        for (int i = 0; i < constraintWidth; i++) {
            tmpS += quoteId(tableFK(firstEdges[i]));
            if (i != constraintWidth - 1) {
                tmpS += ", ";
            }
        }
        tmpS += ')' + $;
        sql.add(tmpS);
        addedUnique.add(pb, firstEdges);
    }
    proc.append("END");
    sql.add(proc.toString());
    addTrigger(pb, "AFTER INSERT", "CALL " + quoteId(insConName) + "(NEW." + quoteId(tablePK(pb)) + ')');
    for (int i = 0; i < constraintWidth; i++) {
        ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> tar = constraint.getTargetPath(i);
        ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> pro = constraint.getProjectionPath(i);
        pbAfterInsertProcs(sql, id, constraint, tar, pro, i);
    }
    // Finally, the before-delete on the pullback:
    final String delConName = "pullbackConstraint" + id + "Delete" + cleanId(pb);
    proc = new StringBuilder(500);
    proc.append("CREATE PROCEDURE ").append(quoteId(delConName)).append("(toDeleteId ").append(pkType()).append(") BEGIN").append(lineSep);
    proc.append("   DELETE ").append(quoteId(target)).append(" FROM ").append(pbQ).append(" JOIN ").append('(');
    for (int i = 0; i < constraintWidth; i++) {
        LinkedList<SketchEdge> tmpPath = new LinkedList<>(constraint.getFullPath(i).getEdges());
        SketchEdge firstEdge = tmpPath.removeFirst();
        @SuppressWarnings("unused") SketchEdge lastEdge = tmpPath.getLast();
        @SuppressWarnings("unused") SketchEdge secondEdge = tmpPath.removeFirst();
        EntityNode first = firstEdge.getTargetEntity();
        proc.append(quoteId(first));
        if (i != constraintWidth - 1) {
            proc.append(", ");
        }
    }
    proc.append(") ON ");
    for (int i = 0; i < constraintWidth; i++) {
        LinkedList<SketchEdge> tmpPath = new LinkedList<>(constraint.getFullPath(i).getEdges());
        SketchEdge firstEdge = tmpPath.removeFirst();
        @SuppressWarnings("unused") SketchEdge lastEdge = tmpPath.getLast();
        @SuppressWarnings("unused") SketchEdge secondEdge = tmpPath.removeFirst();
        EntityNode first = firstEdge.getTargetEntity();
        proc.append(qualifiedFK(firstEdge)).append(" = ").append(qualifiedPK(first));
        if (i != constraintWidth - 1) {
            proc.append(" AND ");
        }
    }
    for (int i = 0; i < constraintWidth; i++) {
        LinkedList<SketchEdge> tmpPath = new LinkedList<>(constraint.getFullPath(i).getEdges());
        SketchEdge firstEdge = tmpPath.removeFirst();
        @SuppressWarnings("unused") SketchEdge lastEdge = tmpPath.getLast();
        SketchEdge secondEdge = tmpPath.removeFirst();
        @SuppressWarnings("unused") EntityNode first = firstEdge.getTargetEntity();
        if (tmpPath.size() > 0) {
            proc.append(" JOIN ").append(joinPath(tmpPath, false, qualifiedFK(secondEdge) + " = " + qualifiedPK(secondEdge.getTargetEntity())));
        }
    }
    proc.append(" JOIN ").append(quoteId(target)).append(" ON ");
    for (int i = 0; i < constraintWidth; i++) {
        LinkedList<SketchEdge> tmpPath = new LinkedList<>(constraint.getFullPath(i).getEdges());
        SketchEdge firstEdge = tmpPath.removeFirst();
        SketchEdge lastEdge = tmpPath.getLast();
        @SuppressWarnings("unused") SketchEdge secondEdge = tmpPath.removeFirst();
        @SuppressWarnings("unused") EntityNode first = firstEdge.getTargetEntity();
        proc.append(qualifiedFK(lastEdge)).append(" = ").append(qualifiedPK(target));
        if (i != constraintWidth - 1) {
            proc.append(" AND ");
        }
    }
    proc.append(lineSep).append("           WHERE ").append(qualifiedPK(pb)).append(" = toDeleteId;").append(lineSep).append("END");
    sql.add(proc.toString());
    addTrigger(pb, "BEFORE DELETE", "CALL " + quoteId(delConName) + "(OLD." + quoteId(tablePK(pb)) + ')');
    // Federico Mora
    int j = 0;
    // c.b_id = b.id JOIN d ON d.c_id = c.id...> WHERE <begin> = id;
    for (int i = 0; i < constraintWidth; i++) {
        ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> p = constraint.getProjectionPath(i);
        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 (int k = 0; k < constraintWidth; k++) {
            ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> q = constraint.getProjectionPath(k);
            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 Update" + constraint.getID() + "Proj" + (j - 1) + "()");
            addTrigger(p.getCoDomain(), "AFTER UPDATE", "CALL Update" + constraint.getID() + "Proj" + (j - 1) + "()");
        }
    }
    return delimit("$$", sql);
}
Also used : LinkedList(java.util.LinkedList) LimitConstraint(easik.model.constraint.LimitConstraint) EqualizerConstraint(easik.model.constraint.EqualizerConstraint) ProductConstraint(easik.model.constraint.ProductConstraint) SumConstraint(easik.model.constraint.SumConstraint) PullbackConstraint(easik.model.constraint.PullbackConstraint) EntityNode(easik.sketch.vertex.EntityNode) SketchGraphModel(easik.sketch.util.graph.SketchGraphModel) SketchFrame(easik.ui.SketchFrame) SketchEdge(easik.sketch.edge.SketchEdge) Sketch(easik.sketch.Sketch)

Example 17 with EntityNode

use of easik.sketch.vertex.EntityNode in project fql by CategoricalData.

the class MySQLExporter method createConstraint.

/**
 * @param constraint
 * @param id
 *
 * @return
 */
@Override
public List<String> createConstraint(final LimitConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> constraint, final String id) {
    final List<String> sql = new LinkedList<>();
    StringBuilder proc = new StringBuilder(500);
    final List<String> declarations = new LinkedList<>();
    final List<String> values = new LinkedList<>();
    final List<String> args = new LinkedList<>();
    final List<String> params = new LinkedList<>();
    // getting the paths involved in this limit constraint
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> coneAB = constraint.getCone().AB;
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> coneBC = constraint.getCone().BC;
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> coneAC = constraint.getCone().AC;
    // TODO this should be in the LimitConstraint
    List<SketchEdge> tmpEdges = coneAB.getEdges();
    tmpEdges.addAll(coneBC.getEdges());
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> coneABC = new ModelPath<>(tmpEdges);
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> limitConeAB = constraint.getLimitCone1().AB;
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> limitCone1BC = constraint.getLimitCone1().BC;
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> limitCone2BC = constraint.getLimitCone2().BC;
    tmpEdges = limitConeAB.getEdges();
    tmpEdges.addAll(limitCone1BC.getEdges());
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> limitCone1ABC = new ModelPath<>(tmpEdges);
    tmpEdges = limitConeAB.getEdges();
    tmpEdges.addAll(limitCone2BC.getEdges());
    ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> limitCone2ABC = new ModelPath<>(tmpEdges);
    ArrayList<ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>> paths = new ArrayList<>();
    paths.add(coneABC);
    paths.add(coneAC);
    paths.add(limitCone1ABC);
    paths.add(coneAB);
    paths.add(limitCone2ABC);
    // would add coneAC, but it's already been added
    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("limitConstraint" + 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);
    // cone commutativity check
    proc.append("        NOT (_cdTarget1 <=> _cdTarget2) OR");
    proc.append(lineSep);
    // limitCone1 commutativity check
    proc.append("        NOT (_cdTarget3 <=> _cdTarget4) OR");
    proc.append(lineSep);
    // limitCone2 commutativity check
    proc.append("        NOT (_cdTarget5 <=> _cdTarget2)");
    proc.append(lineSep);
    proc.append("    THEN CALL constraint_failure('Limit constraint failure.');").append(lineSep).append("    END IF;").append(lineSep).append("END");
    addFail = true;
    sql.addAll(delimit("$$", proc));
    // cast because we will only do this in sketches
    addTrigger(constraint.getCone().getA(), "BEFORE INSERT", "CALL " + quoteId("limitConstraint" + id) + '(' + EasikTools.join(", ", params) + ')');
    return sql;
}
Also used : ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) LimitConstraint(easik.model.constraint.LimitConstraint) EqualizerConstraint(easik.model.constraint.EqualizerConstraint) ProductConstraint(easik.model.constraint.ProductConstraint) SumConstraint(easik.model.constraint.SumConstraint) PullbackConstraint(easik.model.constraint.PullbackConstraint) SketchGraphModel(easik.sketch.util.graph.SketchGraphModel) EntityNode(easik.sketch.vertex.EntityNode) SketchFrame(easik.ui.SketchFrame) SketchEdge(easik.sketch.edge.SketchEdge) ModelPath(easik.model.path.ModelPath) Sketch(easik.sketch.Sketch)

Example 18 with EntityNode

use of easik.sketch.vertex.EntityNode in project fql by CategoricalData.

the class MySQLExporter method pbAfterInsertProcs.

/**
 * @param sql
 * @param id
 * @param constraint
 * @param thisPath
 * @param thisFirstPath
 * @param index
 */
private void pbAfterInsertProcs(final List<String> sql, final String id, final PullbackConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> constraint, final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> thisPath, final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> thisFirstPath, int index) {
    final EntityNode source = thisPath.getDomain();
    final EntityNode pb = thisFirstPath.getDomain();
    final EntityNode target = thisPath.getCoDomain();
    final String insConName = "pullbackConstraint" + id + "Insert" + 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);
    // trigger body
    // omitting last
    final String thisJoinPath = joinPath(thisPath, false);
    // edge
    String lastJoinOn = "JOIN " + quoteId(target) + " ON " + qualifiedFK(thisPath.getLastEdge()) + " = " + qualifiedPK(target);
    for (int i = 0; i < constraint.getWidth(); i++) {
        if (i == index) {
            continue;
        }
        ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> otherPath = constraint.getTargetPath(i);
        lastJoinOn += " AND ";
        lastJoinOn += qualifiedFK(otherPath.getLastEdge()) + " = " + qualifiedPK(target);
    }
    proc.append("\tIF (SELECT COUNT(*) FROM (").append(thisJoinPath);
    for (int i = 0; i < constraint.getWidth(); i++) {
        if (i == index) {
            continue;
        }
        ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> otherPath = constraint.getTargetPath(i);
        proc.append(", ").append(joinPath(otherPath, false));
    }
    proc.append(") ").append(lastJoinOn).append(" WHERE ").append(qualifiedPK(source)).append(" = _newId) > 0 THEN").append(lineSep);
    // constraint condition met
    SketchEdge[] edges;
    for (int i = 0; i < constraint.getWidth(); i++) {
        if (i == index) {
            continue;
        }
        final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> otherPath = constraint.getTargetPath(i);
        final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> otherFirstPath = constraint.getProjectionPath(i);
        final LinkedList<SketchEdge> sketchEdgeLinkedList = otherFirstPath.getEdges();
        edges = sketchEdgeLinkedList.toArray(new SketchEdge[sketchEdgeLinkedList.size()]);
        if (edges.length >= 2) {
            final String joinOn = "JOIN " + quoteId(target) + " ON " + qualifiedFK(thisPath.getLastEdge()) + " = " + qualifiedPK(target) + " AND " + qualifiedFK(otherPath.getLastEdge()) + " = " + qualifiedPK(target);
            // proc.append("\t\tIF (SELECT COUNT(*) FROM
            // (").append(joinPath(sketchEdgeLinkedList, true));
            proc.append("\t\tIF (SELECT COUNT(*) FROM (").append(joinPath(constraint.getFullPath(i).getEdges(), false));
            // TODO might have the same bug if the target path is longer
            // than 1, check this
            proc.append(", ").append(thisJoinPath).append(") ").append(joinOn).append(" WHERE ").append(qualifiedPK(source)).append(" = _newId) = 0 THEN").append(lineSep);
            final LinkedList<SketchEdge> partialPath = new LinkedList<>(otherPath.getEdges());
            for (int j = edges.length - 1; j > 0; j--) {
                final EntityNode s = edges[j].getSourceEntity();
                final EntityNode t = edges[j].getTargetEntity();
                // after s there used to be dest.getShadowEdges();
                proc.append("\t\t\t").append(insertInto(// SELECT
                true, // SELECT
                s, // SELECT
                qualifiedPK(t), // FROM:
                '(' + joinPath(partialPath, false) + ", " + thisJoinPath + ") " + joinOn + " WHERE " + qualifiedPK(source) + " = _newId", Collections.singletonList(quoteId(tableFK(edges[j]))), null));
                partialPath.addFirst(edges[j]);
            }
            proc.append("\t\tEND IF;").append(lineSep);
        }
    }
    final LinkedList<SketchEdge> firstPathEdges = thisFirstPath.getEdges();
    edges = firstPathEdges.toArray(new SketchEdge[firstPathEdges.size()]);
    final LinkedList<SketchEdge> partialPath = new LinkedList<>(thisPath.getEdges());
    for (int i = edges.length - 1; i > 0; i--) {
        final SketchEdge e = edges[i];
        final EntityNode s = e.getSourceEntity();
        final EntityNode t = e.getTargetEntity();
        // after s there used to be dest.getShadowEdges();
        proc.append("\t\t").append(insertInto(true, s, qualifiedPK(t), joinPath(partialPath) + " WHERE " + qualifiedPK(source) + " = _newId", Collections.singletonList(quoteId(tableFK(e))), null));
        partialPath.addFirst(e);
    }
    final EntityNode firstStop = thisFirstPath.getFirstCoDomain();
    final List<String> cols = new LinkedList<>();
    cols.add(quoteId(tableFK(thisFirstPath.getFirstEdge())));
    String tmpStr1 = qualifiedPK(firstStop);
    LinkedList<SketchEdge> tmpPath = new LinkedList<>(constraint.getFullPath(0).getEdges());
    tmpPath.removeFirst();
    String tmpStr2 = '(' + joinPath(tmpPath, false);
    for (int i = 0; i < constraint.getWidth(); i++) {
        final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> otherFirstPath = constraint.getProjectionPath(i);
        final EntityNode otherFirstStop = otherFirstPath.getFirstCoDomain();
        if (otherFirstPath != thisFirstPath) {
            tmpStr1 += ", " + qualifiedPK(otherFirstStop);
            cols.add(quoteId(tableFK(otherFirstPath.getFirstEdge())));
        }
        if (i > 0) {
            tmpPath = new LinkedList<>(constraint.getFullPath(i).getEdges());
            tmpPath.removeFirst();
            tmpStr2 += ", " + joinPath(tmpPath, false);
        }
    }
    // after pb there used to be dest.getShadowEdges();
    proc.append("\t\t").append(insertInto(true, pb, tmpStr1, tmpStr2 + ") " + lastJoinOn + " WHERE " + qualifiedPK(source) + " = _newId", cols, null));
    // end constraint condition met
    proc.append("\tEND IF;");
    // end trigger body
    proc.append(lineSep).append("END");
    sql.add(proc.toString());
    // Now create the trigger to call the new procedure
    addTrigger(source, "AFTER INSERT", "CALL " + quoteId(insConName) + '(' + EasikTools.join(", ", params) + ')');
}
Also used : LinkedList(java.util.LinkedList) LimitConstraint(easik.model.constraint.LimitConstraint) EqualizerConstraint(easik.model.constraint.EqualizerConstraint) ProductConstraint(easik.model.constraint.ProductConstraint) SumConstraint(easik.model.constraint.SumConstraint) PullbackConstraint(easik.model.constraint.PullbackConstraint) EntityNode(easik.sketch.vertex.EntityNode) SketchGraphModel(easik.sketch.util.graph.SketchGraphModel) SketchFrame(easik.ui.SketchFrame) SketchEdge(easik.sketch.edge.SketchEdge) Sketch(easik.sketch.Sketch)

Example 19 with EntityNode

use of easik.sketch.vertex.EntityNode in project fql by CategoricalData.

the class MySQLExporter method createExtras.

/**
 * Creates various extra statements that we need.
 * <p/>
 * One of these is to create a constraint_failure() procedure, since MySQL
 * has no way to abort a transaction other than performing an invalid query
 * (constraint_failure() attempts an "UPDATE" of "fail = 1" on a table named
 * whatever failure message is passed in; that way at least the error
 * appears in the MySQL error message. This sucks, I know. Blame MySQL.)
 * <p/>
 * FIXME: Right now, MySQL <b>does not support</b> updating the same table a
 * trigger applies to in an AFTER trigger, so we have no way to clear shadow
 * columns. This was presumably a result of MySQL incompetence, or MySQL's
 * philosophy of limiting itself in order to prevent idiot PHP programmers
 * from shooting themselves in the foot with--*GASP*--a recursive trigger.
 * While it would be very nice to clear the shadow columns, we simply can't
 * do so: the values are often needed in AFTER INSERT or AFTER UPDATE
 * triggers, so we can't clear them before then, however the only entry
 * point for clearing these with MySQL is doing a 'SET NEW.col = NULL'
 * inside the BEFORE trigger.
 * <p/>
 * If MySQL some day supports an update on the same table a trigger is
 * applied to, the following will work. Until then, MySQL tables will end up
 * retaining values in the shadow columns. N.B. that these values are actual
 * references to the appropriate tables and columns, but are 'ON DELETE SET
 * NULL ON UPDATE SET NULL', so should not pose data manipulation problems.
 *
 * @param toggleTriggers
 *
 * @return
 */
// DTRIG CF2012
@Override
public List<String> createExtras(boolean toggleTriggers) {
    final List<String> extras = new LinkedList<>();
    if (addFail) {
        // This hack is needed for MySQL to abort an insert if a trigger
        // fails.
        // This is disgusting, but is what MySQL documentation recommends
        // doing.
        extras.addAll(delimit("$$", "CREATE PROCEDURE constraint_failure(_message VARCHAR(255)) BEGIN" + lineSep + "   -- This update is going to fail: this hack is needed because MySQL" + lineSep + "   -- lacks the ability to do an (SQL-standard) SIGNAL from a procedure." + lineSep + "   SET @sql = CONCAT('UPDATE `', _message, '` SET fail=1');" + lineSep + "   PREPARE constraint_fail_statement_handle FROM @sql;" + lineSep + "   EXECUTE contraint_fail_statement_handle;" + lineSep + "   DEALLOCATE PREPARE contraint_fail_statement_handle;" + lineSep + "END"));
    }
    final List<StringBuilder> trigs = new LinkedList<>();
    for (final EntityNode table : triggers.keySet()) {
        final LinkedHashMap<String, LinkedList<String>> tableTriggers = triggers.get(table);
        for (final String when : tableTriggers.keySet()) {
            final LinkedList<String> actions = tableTriggers.get(when);
            final StringBuilder commands = new StringBuilder(200);
            commands.append("CREATE TRIGGER ").append(quoteId(table + "_" + when.replaceAll("(\\w)\\w*\\s*", "$1").toLowerCase() + "Trig")).append(' ').append(when).append(" ON ").append(quoteId(table)).append(" FOR EACH ROW").append(lineSep);
            if (toggleTriggers) {
                commands.append("\tIF (@DISABLE_TRIGGER IS NULL) THEN ").append(lineSep);
            }
            if (actions.size() == 1) {
                commands.append(toggleTriggers ? "\t\t" : "\t").append(actions.getFirst()).append(";");
            } else {
                commands.append(toggleTriggers ? "\t\t" : "\t").append("BEGIN").append(lineSep);
                for (final String action : actions) {
                    commands.append(toggleTriggers ? "\t\t\t" : "\t\t").append(action.replaceFirst(";\\s*$", "")).append(';').append(lineSep);
                }
                commands.append(toggleTriggers ? "\t\t" : "\t").append("END;");
            }
            if (toggleTriggers) {
                commands.append(lineSep).append("\tEND IF;").append(lineSep);
            }
            trigs.add(commands);
        }
    }
    if (!trigs.isEmpty()) {
        extras.addAll(delimit("$$", trigs));
    }
    return extras;
}
Also used : LinkedList(java.util.LinkedList) EntityNode(easik.sketch.vertex.EntityNode)

Example 20 with EntityNode

use of easik.sketch.vertex.EntityNode in project fql by CategoricalData.

the class MySQLExporter method createReferences.

/**
 * @param table
 *
 * @return
 */
@Override
public List<String> createReferences(final EntityNode table) {
    final List<String> refs = new LinkedList<>();
    final String tableQ = quoteId(table);
    for (final SketchEdge edge : table.getOutgoingEdges()) {
        final EntityNode target = edge.getTargetEntity();
        // No
        final String refMode = (edge.getCascading() == SketchEdge.Cascade.SET_NULL) ? "SET NULL" : (edge.getCascading() == SketchEdge.Cascade.CASCADE) ? "CASCADE" : "NO ACTION";
        // different
        // from
        // RESTRICT
        // under
        // MySQL
        // (in
        // theory,
        // RESTRICT
        // shouldn't
        // work
        // even
        // if
        // cleaned
        // up
        // in
        // the
        // same
        // transaction,
        // while
        // NO
        // ACTION
        // should)
        refs.add("ALTER TABLE " + tableQ + " ADD FOREIGN KEY (" + quoteId(tableFK(edge)) + ") " + "REFERENCES " + quoteId(target) + " (" + quoteId(tablePK(target)) + ") " + "ON DELETE " + refMode + " ON UPDATE " + refMode + $);
    }
    /**
     * // We need a copy of any sum tables' not-null columns (which are
     * simply the // outgoing, non-partial edges) if this table is a
     * summand; we shadow the // columns here, then handle propagating them
     * in the SumConstraint triggers. for (final SketchEdge edge :
     * table.getShadowEdges()) { refs.add("ALTER TABLE " + tableQ + " ADD
     * COLUMN " + quoteId(tableFK(edge)) + ' ' + pkType()); refs.add("ALTER
     * TABLE " + tableQ + " ADD FOREIGN KEY (" + quoteId(tableFK(edge)) + ")
     * REFERENCES " + quoteId(edge.getTargetEntity()) + " (" +
     * quoteId(tablePK(edge.getTargetEntity())) + ") " + "ON DELETE SET NULL
     * ON UPDATE SET NULL"); }
     */
    return refs;
}
Also used : SketchEdge(easik.sketch.edge.SketchEdge) LinkedList(java.util.LinkedList) EntityNode(easik.sketch.vertex.EntityNode)

Aggregations

EntityNode (easik.sketch.vertex.EntityNode)62 SketchEdge (easik.sketch.edge.SketchEdge)45 Sketch (easik.sketch.Sketch)30 SketchGraphModel (easik.sketch.util.graph.SketchGraphModel)30 SketchFrame (easik.ui.SketchFrame)29 LinkedList (java.util.LinkedList)21 LimitConstraint (easik.model.constraint.LimitConstraint)16 ProductConstraint (easik.model.constraint.ProductConstraint)15 PullbackConstraint (easik.model.constraint.PullbackConstraint)15 SumConstraint (easik.model.constraint.SumConstraint)15 EqualizerConstraint (easik.model.constraint.EqualizerConstraint)12 ModelConstraint (easik.model.constraint.ModelConstraint)12 ArrayList (java.util.ArrayList)12 ModelPath (easik.model.path.ModelPath)8 InjectiveEdge (easik.sketch.edge.InjectiveEdge)7 UpdateMonitor (easik.ui.datamanip.UpdateMonitor)6 SQLException (java.sql.SQLException)6 LinkedHashSet (java.util.LinkedHashSet)6 QueryNode (easik.view.vertex.QueryNode)5 XSDAnnotation (easik.xml.xsd.nodes.XSDAnnotation)5