diff --git a/releasenotes.txt b/releasenotes.txt index 181c4a0ac..b7dcd427b 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -1,3 +1,6 @@ +7.5.8 + - SQLConsole: added ability to execute SQL fragments. + 7.5.7 - Minor GUI improvements. diff --git a/src/main/engine/net/sf/jailer/JailerVersion.java b/src/main/engine/net/sf/jailer/JailerVersion.java index a65cf6533..86ae06016 100644 --- a/src/main/engine/net/sf/jailer/JailerVersion.java +++ b/src/main/engine/net/sf/jailer/JailerVersion.java @@ -25,7 +25,7 @@ public class JailerVersion { /** * The Jailer version. */ - public static final String VERSION = "7.5.7"; + public static final String VERSION = "7.5.8"; /** * The Jailer working tables version. diff --git a/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java b/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java index b9c1c9f67..35fa2dc72 100644 --- a/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java +++ b/src/main/gui/net/sf/jailer/ui/databrowser/sqlconsole/SQLConsole.java @@ -340,8 +340,9 @@ public abstract class SQLConsole extends javax.swing.JPanel { * @param sqlBlock the sql block * @param location location of the block in the console * @param emptyLineSeparatesStatements + * @param locFragmentOffset location of statement fragment, if any */ - protected void executeSQLBlock(final String sqlBlock, final Pair location, final boolean emptyLineSeparatesStatements) { + protected void executeSQLBlock(final String sqlBlock, final Pair location, final boolean emptyLineSeparatesStatements, final Pair locFragmentOffset) { if (!running.get()) { int lineStartOffset = -1; try { @@ -380,17 +381,33 @@ public abstract class SQLConsole extends javax.swing.JPanel { Matcher matcher = pattern.matcher(sqlBlock); boolean result = matcher.find(); StringBuffer sb = new StringBuffer(); - if (result) { + if (result || locFragmentOffset != null) { do { - sb.setLength(0); - matcher.appendReplacement(sb, ""); - String pureSql = sb.toString(); - sb.append(matcher.group()); - String sql = sb.toString(); + String sql; + String pureSql; + if (locFragmentOffset != null) { + sql = sqlBlock; + pureSql = sqlBlock; + } else { + sb.setLength(0); + matcher.appendReplacement(sb, ""); + pureSql = sb.toString(); + sb.append(matcher.group()); + sql = sb.toString(); + } status.linesExecuting += countLines(pureSql); if (sql.trim().length() > 0) { executeSQL(pureSql, status, lineStartOffset); if (status.failed) { + if (locFragmentOffset != null) { + status.sqlFragment = sql; + if (status.errorPositionIsKnown) { + try { + status.errorPosition += locFragmentOffset.a - editorPane.getLineStartOffset(editorPane.getLineOfOffset(locFragmentOffset.a)); + } catch (BadLocationException e) { + } + } + } break; } } @@ -398,6 +415,9 @@ public abstract class SQLConsole extends javax.swing.JPanel { lineStartOffset += sql.length(); } status.linesExecuted += countLines(sql) - 1; + if (locFragmentOffset != null) { + break; + } String terminator = matcher.group(1); if (terminator != null && !terminator.contains("\n")) { // ';' without nl status.linesExecuted++; @@ -406,7 +426,7 @@ public abstract class SQLConsole extends javax.swing.JPanel { result = matcher.find(); } while (result); } - if (!status.failed) { + if (!status.failed && locFragmentOffset == null) { sb.setLength(0); matcher.appendTail(sb); String sbToString = sb.toString(); @@ -645,6 +665,7 @@ public abstract class SQLConsole extends javax.swing.JPanel { boolean hasUpdated = false; long timeInMS; Throwable error; + String sqlFragment; Pair location; private synchronized void updateView(boolean force) { @@ -687,7 +708,9 @@ public abstract class SQLConsole extends javax.swing.JPanel { if (errorLine >= 0) { editorPane.setLineTrackingIcon(errorLine, scaledCancelIcon); } - statusTextPane.setText(pos + error.getMessage()); + statusTextPane.setText(pos + error.getMessage() + + (sqlFragment == null? "" : + "\nSQL: \"" + (sqlFragment.trim()) + "\"")); } else { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); @@ -1188,16 +1211,32 @@ public abstract class SQLConsole extends javax.swing.JPanel { } private void executeSelectedStatements() { - Pair loc = editorPane.getCurrentStatementLocation(null); + String sql; + Pair loc = null; + Pair locFragmentOffset = null; + Pair, Pair> locFragment = editorPane.getCurrentStatementFragmentLocation(); + if (locFragment != null) { + loc = locFragment.a; + locFragmentOffset = locFragment.b; + try { + sql = editorPane.getDocument().getText(locFragmentOffset.a, locFragmentOffset.b - locFragmentOffset.a); + } catch (BadLocationException e) { + e.printStackTrace(); + return; + } + } else { + loc = editorPane.getCurrentStatementLocation(null); + sql = editorPane.getText(loc.a, loc.b, true); + } if (loc != null) { - executeSQLBlock(editorPane.getText(loc.a, loc.b, true), loc, editorPane.getCaret().getDot() == editorPane.getCaret().getMark()); + executeSQLBlock(sql, loc, true, locFragmentOffset); } } private void executeAllStatements() { if (editorPane.getLineCount() > 0) { Pair loc = new Pair(0, editorPane.getLineCount() - 1); - executeSQLBlock(editorPane.getText(loc.a, loc.b, true), loc, false); + executeSQLBlock(editorPane.getText(loc.a, loc.b, true), loc, true, null); } } diff --git a/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebegin.png b/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebegin.png index b27b32b66..369bb620c 100644 Binary files a/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebegin.png and b/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebegin.png differ diff --git a/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebeginend.png b/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebeginend.png index e16f17619..c3f1fb2b7 100644 Binary files a/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebeginend.png and b/src/main/gui/net/sf/jailer/ui/resource/sqlconsolebeginend.png differ diff --git a/src/main/gui/net/sf/jailer/ui/resource/sqlconsoleend.png b/src/main/gui/net/sf/jailer/ui/resource/sqlconsoleend.png index d46d372f8..fd9f8c49c 100644 Binary files a/src/main/gui/net/sf/jailer/ui/resource/sqlconsoleend.png and b/src/main/gui/net/sf/jailer/ui/resource/sqlconsoleend.png differ diff --git a/src/main/gui/net/sf/jailer/ui/syntaxtextarea/RSyntaxTextAreaWithSQLSyntaxStyle.java b/src/main/gui/net/sf/jailer/ui/syntaxtextarea/RSyntaxTextAreaWithSQLSyntaxStyle.java index 91513d6dc..9a7a00ac3 100644 --- a/src/main/gui/net/sf/jailer/ui/syntaxtextarea/RSyntaxTextAreaWithSQLSyntaxStyle.java +++ b/src/main/gui/net/sf/jailer/ui/syntaxtextarea/RSyntaxTextAreaWithSQLSyntaxStyle.java @@ -103,6 +103,10 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement iconBegin = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsolebegin.png"))); iconBeginEnd = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsolebeginend.png"))); iconEnd = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsoleend.png"))); + iconf = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsolef.png"))); + iconBeginf = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsolebeginf.png"))); + iconBeginEndf = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsolebeginendf.png"))); + iconEndf = scaleToLineHeight(new ImageIcon(MetaDataPanel.class.getResource(dir + "/sqlconsoleendf.png"))); } catch (Exception e) { e.printStackTrace(); } @@ -276,7 +280,7 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement } /** - * Gets statement(s) at caret position. + * Replaces statement(s) at caret position. * * @param replacement * the replacement @@ -359,6 +363,34 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement return true; } + /** + * Gets start- and end-line number of statement fragment at caret position, if any. + * + * @return pair of (start and end line number) and (begin- end-offset) + */ + public Pair, Pair> getCurrentStatementFragmentLocation() { + int begin = Math.min(getCaret().getDot(), getCaret().getMark()); + int end = Math.max(getCaret().getDot(), getCaret().getMark()); + if (begin == end || end - begin > 1000000) { + return null; + } + Segment txt = new Segment(); + try { + getDocument().getText(begin, end - begin, txt); + Pattern pattern = Pattern.compile("(\\n\\s*\\n)|(;\\s*(\\n\\r?|$))", Pattern.DOTALL); + Matcher matcher = pattern.matcher(txt); + if (!matcher.find()) { + return new Pair, Pair>( + new Pair(getLineOfOffset(begin), getLineOfOffset(end)), + new Pair(begin, end) + ); + } + } catch (BadLocationException e) { + return null; + } + return null; + } + /** * Gets start- and end-line number of statement(s) at caret position. * @@ -571,7 +603,15 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement public void updateMenuItemState(boolean allowRun, boolean setLineHighlights) { Set eosLines = new HashSet(); - Pair loc = getCurrentStatementLocation(eosLines); + Pair loc; + Pair locFragmentOffset = null; + Pair, Pair> locFragment = getCurrentStatementFragmentLocation(); + if (locFragment != null) { + loc = locFragment.a; + locFragmentOffset = locFragment.b; + } else { + loc = getCurrentStatementLocation(eosLines); + } runBlock.setEnabled(allowRun && loc != null && !isTextEmpty(loc.a, loc.b)); runAll.setEnabled(allowRun && RSyntaxTextAreaWithSQLSyntaxStyle.this.getDocument().getLength() > 0); if (allowRun && setLineHighlights) { @@ -593,19 +633,26 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement } else { theIcon = icon; } + if (locFragmentOffset != null) { + if (theIcon == icon) { + theIcon = iconf; + } + if (theIcon == iconBegin) { + theIcon = iconBeginf; + } + if (theIcon == iconBeginEnd) { + theIcon = iconBeginEndf; + } + if (theIcon == iconEnd) { + theIcon = iconEndf; + } + } gutter.addLineTrackingIcon(l, theIcon); } } } catch (BadLocationException e) { } } -// for (int l = loc.a; l <= loc.b; ++l) { -// try { -// addLineHighlight(l, new Color(235, 255, 245)); -// } catch (BadLocationException e) { -// e.printStackTrace(); -// } -// } if (loc.b - loc.a > 10000) { stopped.set(false); pending.set(true); @@ -683,5 +730,9 @@ public class RSyntaxTextAreaWithSQLSyntaxStyle extends RSyntaxTextArea implement private ImageIcon iconBegin; private ImageIcon iconBeginEnd; private ImageIcon iconEnd; + private ImageIcon iconf; + private ImageIcon iconBeginf; + private ImageIcon iconBeginEndf; + private ImageIcon iconEndf; }