Repository: zeppelin
Updated Branches:
  refs/heads/master af1899136 -> f6b58ee5a


[HOTFIX] JDBC completions. fix cursor position

### What is this PR for?
If text of paragraph contains interpreter name then parser works incorrect 
(cursor position  incorrect).

### What type of PR is it?
Bug Fix

### Screenshots (if appropriate)
before
![before](https://user-images.githubusercontent.com/25951039/28326867-55195f50-6bfb-11e7-8f93-c381658d598a.png)
after
![after](https://user-images.githubusercontent.com/25951039/28326904-6f053fa6-6bfb-11e7-8586-00da4fa95b21.png)

### Questions:
* Does the licenses files need update? no
* Is there breaking changes for older versions? no
* Does this needs documentation? no

Author: tinkoff-dwh <tinkoff....@gmail.com>
Author: Tinkoff DWH <tinkoff....@gmail.com>

Closes #2495 from tinkoff-dwh/completion_hotfix and squashes the following 
commits:

bac1ac2 [tinkoff-dwh] Merge remote-tracking branch 'upstream/master' into 
completion_hotfix
80c8e2a [Tinkoff DWH] small refactoring
5e9aa73 [tinkoff-dwh] add more data to dataset of test
9f3dbc7 [tinkoff-dwh] added test
43f8ffd [tinkoff-dwh] another solution to fix cursor position + small fix to 
return table names
4e6347a [Tinkoff DWH] fix cursor position for completions


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/f6b58ee5
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/f6b58ee5
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/f6b58ee5

Branch: refs/heads/master
Commit: f6b58ee5a06d32af37903cc768e106079d267b2d
Parents: af18991
Author: tinkoff-dwh <tinkoff....@gmail.com>
Authored: Mon Jul 31 15:56:34 2017 +0500
Committer: Lee moon soo <m...@apache.org>
Committed: Sun Aug 20 22:33:04 2017 -0700

----------------------------------------------------------------------
 .../org/apache/zeppelin/jdbc/SqlCompleter.java  |  3 +-
 .../org/apache/zeppelin/notebook/Paragraph.java | 85 ++++++++++++++------
 .../apache/zeppelin/notebook/ParagraphTest.java | 43 ++++++++--
 3 files changed, 97 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/f6b58ee5/jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java 
b/jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java
index 46cc4bd..6103fc7 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java
@@ -179,7 +179,8 @@ public class SqlCompleter {
 
 
   private static void fillTableNames(String schema, DatabaseMetaData meta, 
Set<String> tables) {
-    try (ResultSet tbls = meta.getTables(schema, schema, "%", null)) {
+    try (ResultSet tbls = meta.getTables(schema, schema, "%",
+        new String[]{"TABLE", "VIEW", "ALIAS", "SYNONYM", "GLOBAL TEMPORARY", 
"LOCAL TEMPORARY"})) {
       while (tbls.next()) {
         String table = tbls.getString("TABLE_NAME");
         tables.add(table);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/f6b58ee5/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
index ac3d19f..37138e6 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
@@ -17,35 +17,58 @@
 
 package org.apache.zeppelin.notebook;
 
-import com.google.common.collect.Maps;
-import com.google.common.base.Strings;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.zeppelin.common.JsonSerializable;
 import org.apache.zeppelin.completer.CompletionType;
 import org.apache.zeppelin.display.AngularObject;
 import org.apache.zeppelin.display.AngularObjectRegistry;
-import org.apache.zeppelin.helium.HeliumPackage;
-import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
-import org.apache.zeppelin.user.AuthenticationInfo;
-import org.apache.zeppelin.user.Credentials;
-import org.apache.zeppelin.user.UserCredentials;
 import org.apache.zeppelin.display.GUI;
 import org.apache.zeppelin.display.Input;
-import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.helium.HeliumPackage;
+import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.Interpreter.FormType;
+import org.apache.zeppelin.interpreter.InterpreterContext;
+import org.apache.zeppelin.interpreter.InterpreterContextRunner;
+import org.apache.zeppelin.interpreter.InterpreterException;
+import org.apache.zeppelin.interpreter.InterpreterFactory;
+import org.apache.zeppelin.interpreter.InterpreterInfo;
+import org.apache.zeppelin.interpreter.InterpreterOption;
+import org.apache.zeppelin.interpreter.InterpreterOutput;
+import org.apache.zeppelin.interpreter.InterpreterOutputListener;
+import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.InterpreterResultMessage;
+import org.apache.zeppelin.interpreter.InterpreterResultMessageOutput;
+import org.apache.zeppelin.interpreter.InterpreterSetting;
+import org.apache.zeppelin.interpreter.InterpreterSettingManager;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.resource.ResourcePool;
 import org.apache.zeppelin.scheduler.Job;
 import org.apache.zeppelin.scheduler.JobListener;
 import org.apache.zeppelin.scheduler.Scheduler;
+import org.apache.zeppelin.user.AuthenticationInfo;
+import org.apache.zeppelin.user.Credentials;
+import org.apache.zeppelin.user.UserCredentials;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.*;
-
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
 
 /**
  * Paragraph is a representation of an execution unit.
@@ -204,7 +227,7 @@ public class Paragraph extends Job implements Cloneable, 
JsonSerializable {
   }
 
   public String getRequiredReplName() {
-    return getRequiredReplName(text);
+    return getRequiredReplName(text != null ? text.trim() : text);
   }
 
   public static String getRequiredReplName(String text) {
@@ -212,15 +235,14 @@ public class Paragraph extends Job implements Cloneable, 
JsonSerializable {
       return null;
     }
 
-    String trimmed = text.trim();
-    if (!trimmed.startsWith("%")) {
+    if (!text.startsWith("%")) {
       return null;
     }
 
     // get script head
     int scriptHeadIndex = 0;
-    for (int i = 0; i < trimmed.length(); i++) {
-      char ch = trimmed.charAt(i);
+    for (int i = 0; i < text.length(); i++) {
+      char ch = text.charAt(i);
       if (Character.isWhitespace(ch) || ch == '(' || ch == '\n') {
         break;
       }
@@ -247,11 +269,10 @@ public class Paragraph extends Job implements Cloneable, 
JsonSerializable {
       return text;
     }
 
-    String trimmed = text.trim();
-    if (magic.length() + 1 >= trimmed.length()) {
+    if (magic.length() + 1 >= text.length()) {
       return "";
     }
-    return trimmed.substring(magic.length() + 1).trim();
+    return text.substring(magic.length() + 1).trim();
   }
 
   public Interpreter getRepl(String name) {
@@ -288,13 +309,12 @@ public class Paragraph extends Job implements Cloneable, 
JsonSerializable {
         return getInterpreterCompletion();
       }
     }
+    String trimmedBuffer = buffer != null ? buffer.trim() : null;
+    cursor = calculateCursorPosition(buffer, trimmedBuffer, cursor);
 
-    String replName = getRequiredReplName(buffer);
-    if (replName != null && cursor > replName.length()) {
-      cursor -= replName.length() + 1;
-    }
+    String replName = getRequiredReplName(trimmedBuffer);
 
-    String body = getScriptBody(buffer);
+    String body = getScriptBody(trimmedBuffer);
     Interpreter repl = getRepl(replName);
     if (repl == null) {
       return null;
@@ -306,6 +326,21 @@ public class Paragraph extends Job implements Cloneable, 
JsonSerializable {
     return completion;
   }
 
+  public int calculateCursorPosition(String buffer, String trimmedBuffer, int 
cursor) {
+    int countWhitespacesAtStart = buffer.indexOf(trimmedBuffer);
+    if (countWhitespacesAtStart > 0) {
+      cursor -= countWhitespacesAtStart;
+    }
+
+    String replName = getRequiredReplName(trimmedBuffer);
+    if (replName != null && cursor > replName.length()) {
+      String body = trimmedBuffer.substring(replName.length() + 1);
+      cursor -= replName.length() + 1 + body.indexOf(body.trim());
+    }
+
+    return cursor;
+  }
+
   public void setInterpreterFactory(InterpreterFactory factory) {
     this.factory = factory;
   }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/f6b58ee5/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
index 0e77846..7bd6819 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
@@ -21,10 +21,7 @@ package org.apache.zeppelin.notebook;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -33,7 +30,11 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import com.google.common.collect.Lists;
+
+import java.util.Arrays;
 import java.util.List;
+
+import org.apache.commons.lang3.tuple.Triple;
 import org.apache.zeppelin.display.AngularObject;
 import org.apache.zeppelin.display.AngularObjectBuilder;
 import org.apache.zeppelin.display.AngularObjectRegistry;
@@ -41,7 +42,6 @@ import org.apache.zeppelin.display.Input;
 import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.Interpreter.FormType;
 import org.apache.zeppelin.interpreter.InterpreterContext;
-import org.apache.zeppelin.interpreter.InterpreterFactory;
 import org.apache.zeppelin.interpreter.InterpreterGroup;
 import org.apache.zeppelin.interpreter.InterpreterOption;
 import org.apache.zeppelin.interpreter.InterpreterResult;
@@ -52,14 +52,12 @@ import org.apache.zeppelin.interpreter.InterpreterSetting;
 import org.apache.zeppelin.interpreter.InterpreterSetting.Status;
 import org.apache.zeppelin.interpreter.InterpreterSettingManager;
 import org.apache.zeppelin.resource.ResourcePool;
-import org.apache.zeppelin.scheduler.JobListener;
 import org.apache.zeppelin.user.AuthenticationInfo;
 import org.apache.zeppelin.user.Credentials;
 import org.junit.Test;
 
 import java.util.HashMap;
 import java.util.Map;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
 public class ParagraphTest {
@@ -228,8 +226,37 @@ public class ParagraphTest {
     assertNotEquals(p1.getReturn().toString(), p2.getReturn().toString());
 
     assertEquals(p1, spyParagraph.getUserParagraph(user1.getUser()));
+  }
 
-
-
+  @Test
+  public void testCursorPosition() {
+    Paragraph paragraph = spy(new Paragraph());
+    doReturn(null).when(paragraph).getRepl(anyString());
+    // left = buffer, middle = cursor position into source code, right = 
cursor position after parse
+    List<Triple<String, Integer, Integer>> dataSet = Arrays.asList(
+        Triple.of("%jdbc schema.", 13, 7),
+        Triple.of("   %jdbc schema.", 16, 7),
+        Triple.of(" \n%jdbc schema.", 15, 7),
+        Triple.of("%jdbc schema.table.  ", 19, 13),
+        Triple.of("%jdbc schema.\n\n", 13, 7),
+        Triple.of("  %jdbc schema.tab\n\n", 18, 10),
+        Triple.of("  \n%jdbc schema.\n \n", 16, 7),
+        Triple.of("  \n%jdbc schema.\n \n", 16, 7),
+        Triple.of("  \n%jdbc\n\n schema\n \n", 17, 6),
+        Triple.of("%another\n\n schema.", 18, 7),
+        Triple.of("\n\n schema.", 10, 7),
+        Triple.of("schema.", 7, 7),
+        Triple.of("schema. \n", 7, 7),
+        Triple.of("  \n   %jdbc", 11, 0),
+        Triple.of("\n   %jdbc", 9, 0),
+        Triple.of("%jdbc  \n  schema", 16, 6),
+        Triple.of("%jdbc  \n  \n   schema", 20, 6)
+    );
+
+    for (Triple<String, Integer, Integer> data : dataSet) {
+      Integer actual = paragraph.calculateCursorPosition(data.getLeft(), 
data.getLeft().trim(), data.getMiddle());
+      assertEquals(data.getRight(), actual);
+    }
   }
+
 }

Reply via email to