You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by ja...@apache.org on 2013/08/06 01:47:44 UTC
[2/3] git commit: Implement negative substring offset
Implement negative substring offset
Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/068a1dfd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/068a1dfd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/068a1dfd
Branch: refs/heads/master
Commit: 068a1dfddde0ef16db9b003cf7b28a79911417b5
Parents: ce7cf0d
Author: Ben Becker <be...@gmail.com>
Authored: Fri Aug 2 12:31:16 2013 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Mon Aug 5 16:44:57 2013 -0700
----------------------------------------------------------------------
.../drill/exec/expr/fn/impl/Substring.java | 37 +++++++++++++++++--
.../exec/physical/impl/TestSimpleFunctions.java | 38 ++++++++++++++++++++
.../test/resources/functions/testSubstring.json | 2 +-
.../functions/testSubstringNegative.json | 37 +++++++++++++++++++
4 files changed, 110 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/068a1dfd/sandbox/prototype/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Substring.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Substring.java b/sandbox/prototype/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Substring.java
index 785ed7d..5466159 100644
--- a/sandbox/prototype/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Substring.java
+++ b/sandbox/prototype/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Substring.java
@@ -30,8 +30,22 @@ import org.apache.drill.exec.record.RecordBatch;
import org.apache.drill.exec.vector.*;
// TODO: implement optional length parameter
-// implement negative start position
+// implement UTF-8 and UTF-16 support
+/**
+ * Evaluate a substring expression for a given value; specifying the start
+ * position, and optionally the end position.
+ *
+ * - If the start position is negative, start from abs(start) characters from
+ * the end of the buffer.
+ *
+ * - If no length is specified, continue to the end of the string.
+ *
+ * - If the substring expression's length exceeds the value's upward bound, the
+ * value's length will be used.
+ *
+ * - If the substring is invalid, return an empty string.
+ */
@FunctionTemplate(name = "substring",
scope = FunctionTemplate.FunctionScope.SIMPLE,
nulls = FunctionTemplate.NullHandling.NULL_IF_NULL)
@@ -48,8 +62,25 @@ public class Substring implements DrillFunc {
@Override
public void eval() {
out.buffer = string.buffer;
- out.start = (int)offset.value;
- out.end = (int)length.value;
+
+ // handle invalid values; e.g. SUBSTRING(value, 0, x) or SUBSTRING(value, x, 0)
+ if (offset.value == 0 || length.value <= 0) {
+ out.start = 0;
+ out.end = 0;
+ return;
+ }
+
+ // handle negative and positive offset values
+ if (offset.value < 0)
+ out.start = string.end + (int)offset.value;
+ else
+ out.start = (int)offset.value - 1;
+
+ // calculate end position from length and truncate to upper value bounds
+ if (out.start + length.value > string.end)
+ out.end = string.end;
+ else
+ out.end = out.start + (int)length.value;
}
public static class Provider implements CallProvider {
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/068a1dfd/sandbox/prototype/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestSimpleFunctions.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestSimpleFunctions.java b/sandbox/prototype/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestSimpleFunctions.java
index bed976c..17932e7 100644
--- a/sandbox/prototype/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestSimpleFunctions.java
+++ b/sandbox/prototype/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestSimpleFunctions.java
@@ -143,6 +143,44 @@ public class TestSimpleFunctions {
}
+ @Test
+ public void testSubstringNegative(@Injectable final DrillbitContext bitContext,
+ @Injectable UserServer.UserClientConnection connection) throws Throwable{
+
+ new NonStrictExpectations(){{
+ bitContext.getMetrics(); result = new MetricRegistry("test");
+ bitContext.getAllocator(); result = BufferAllocator.getAllocator(c);
+ }};
+
+ PhysicalPlanReader reader = new PhysicalPlanReader(c, c.getMapper(), CoordinationProtos.DrillbitEndpoint.getDefaultInstance());
+ PhysicalPlan plan = reader.readPhysicalPlan(Files.toString(FileUtils.getResourceAsFile("/functions/testSubstringNegative.json"), Charsets.UTF_8));
+ FunctionImplementationRegistry registry = new FunctionImplementationRegistry(c);
+ FragmentContext context = new FragmentContext(bitContext, ExecProtos.FragmentHandle.getDefaultInstance(), connection, null, registry);
+ SimpleRootExec exec = new SimpleRootExec(ImplCreator.getExec(context, (FragmentRoot) plan.getSortedOperators(false).iterator().next()));
+
+ while(exec.next()){
+ NullableVarCharVector c1 = exec.getValueVectorById(new SchemaPath("col3", ExpressionPosition.UNKNOWN), NullableVarCharVector.class);
+ NullableVarCharVector.Accessor a1;
+ a1 = c1.getAccessor();
+
+ int count = 0;
+ for(int i = 0; i < c1.getAccessor().getValueCount(); i++){
+ if (!a1.isNull(i)) {
+ NullableVarCharHolder holder = new NullableVarCharHolder();
+ a1.get(i, holder);
+ assertEquals("aa", holder.toString());
+ ++count;
+ }
+ }
+ assertEquals(50, count);
+ }
+
+ if(context.getFailureCause() != null){
+ throw context.getFailureCause();
+ }
+ assertTrue(!context.isFailed());
+
+ }
@After
public void tearDown() throws Exception{
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/068a1dfd/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstring.json
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstring.json b/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstring.json
index 33b0da0..08a8ece 100644
--- a/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstring.json
+++ b/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstring.json
@@ -25,7 +25,7 @@
child: 1,
pop:"project",
exprs: [
- { ref: "col3", expr:"substring(yellow, 0, 4)" }
+ { ref: "col3", expr:"substring(yellow, 1, 4)" }
]
},
{
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/068a1dfd/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstringNegative.json
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstringNegative.json b/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstringNegative.json
new file mode 100644
index 0000000..4951913
--- /dev/null
+++ b/sandbox/prototype/exec/java-exec/src/test/resources/functions/testSubstringNegative.json
@@ -0,0 +1,37 @@
+{
+ head:{
+ type:"APACHE_DRILL_PHYSICAL",
+ version:"1",
+ generator:{
+ type:"manual"
+ }
+ },
+ graph:[
+ {
+ @id:1,
+ pop:"mock-scan",
+ url: "http://apache.org",
+ entries:[
+ {records: 100, types: [
+ {name: "blue", type: "INT", mode: "REQUIRED"},
+ {name: "red", type: "BIGINT", mode: "REQUIRED"},
+ {name: "yellow", type: "VARCHAR", mode: "OPTIONAL"},
+ {name: "green", type: "INT", mode: "REQUIRED"}
+ ]}
+ ]
+ },
+ {
+ @id:2,
+ child: 1,
+ pop:"project",
+ exprs: [
+ { ref: "col3", expr:"substring(yellow, -3, 2)" }
+ ]
+ },
+ {
+ @id: 3,
+ child: 2,
+ pop: "screen"
+ }
+ ]
+}
\ No newline at end of file