http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ValueHolderReplacementVisitor.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ValueHolderReplacementVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ValueHolderReplacementVisitor.java new file mode 100644 index 0000000..2cec537 --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ValueHolderReplacementVisitor.java @@ -0,0 +1,75 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.drill.exec.compile.bytecode; + +import java.io.PrintWriter; + +import org.apache.commons.io.output.StringBuilderWriter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.util.Textifier; +import org.objectweb.asm.util.TraceMethodVisitor; + +public class ValueHolderReplacementVisitor extends ClassVisitor { + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ValueHolderReplacementVisitor.class); + + public ValueHolderReplacementVisitor(ClassVisitor cw) { + super(Opcodes.ASM4, cw); + } + + + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor innerVisitor = super.visitMethod(access, name, desc, signature, exceptions); +// innerVisitor = new Debugger(access, name, desc, signature, exceptions, innerVisitor); + return new ScalarReplacementNode(access, name, desc, signature, exceptions, innerVisitor); + } + + private static class Debugger extends MethodNode { + + MethodVisitor inner; + + public Debugger(int access, String name, String desc, String signature, String[] exceptions, MethodVisitor inner) { + super(access, name, desc, signature, exceptions); + this.inner = inner; + + } + + @Override + public void visitEnd() { + try{ + accept(inner); + }catch(Exception e){ + Textifier t = new Textifier(); + accept(new TraceMethodVisitor(t)); + StringBuilderWriter sw = new StringBuilderWriter(); + PrintWriter pw = new PrintWriter(sw); + t.print(pw); + pw.flush(); + String bytecode = sw.getBuilder().toString(); + logger.error(String.format("Failure while rendering method %s, %s, %s. ByteCode:\n %s", name, desc, signature, bytecode), e); + throw new RuntimeException(String.format("Failure while rendering method %s, %s, %s. ByteCode:\n %s", name, desc, signature, bytecode), e); + } + + } + + } +}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/CodeGeneratorMethod.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/CodeGeneratorMethod.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/CodeGeneratorMethod.java index 9fe0cf3..a7b5680 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/CodeGeneratorMethod.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/CodeGeneratorMethod.java @@ -28,13 +28,21 @@ import com.thoughtworks.paranamer.Paranamer; public class CodeGeneratorMethod implements Iterable<CodeGeneratorArgument>{ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CodeGeneratorMethod.class); - + private final String methodName; private final Class<?> returnType; private final CodeGeneratorArgument[] arguments; private final Class<?>[] exs; private final Method underlyingMethod; - + + public CodeGeneratorMethod(String name, Class<?> returnType){ + this.methodName = name; + this.returnType = returnType; + this.exs = new Class<?>[0]; + this.underlyingMethod = null; + this.arguments = new CodeGeneratorArgument[0]; + } + public CodeGeneratorMethod(Method m){ this.underlyingMethod = m; this.methodName = m.getName(); @@ -51,7 +59,7 @@ public class CodeGeneratorMethod implements Iterable<CodeGeneratorArgument>{ } exs = m.getExceptionTypes(); } - + public String getMethodName() { return methodName; } @@ -62,7 +70,7 @@ public class CodeGeneratorMethod implements Iterable<CodeGeneratorArgument>{ public Iterable<Class<?>> getThrowsIterable(){ return ImmutableList.copyOf(exs); } - + @Override public Iterator<CodeGeneratorArgument> iterator() { return Iterators.forArray(arguments); @@ -73,5 +81,5 @@ public class CodeGeneratorMethod implements Iterable<CodeGeneratorArgument>{ return "CodeGeneratorMethod [" + underlyingMethod.toGenericString() + "]"; } - + } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/GeneratorMapping.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/GeneratorMapping.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/GeneratorMapping.java index 70a3cda..57551ed 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/GeneratorMapping.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/GeneratorMapping.java @@ -28,7 +28,7 @@ public class GeneratorMapping { private String eval; private String reset; private String cleanup; - + public GeneratorMapping(String setup, String eval, String reset, String cleanup) { super(); @@ -49,15 +49,15 @@ public class GeneratorMapping { public static GeneratorMapping GM(String setup, String eval){ return create(setup, eval, null, null); } - + public static GeneratorMapping GM(String setup, String eval, String reset, String cleanup){ return create(setup, eval, reset, cleanup); } - public static GeneratorMapping create(String setup, String eval, String reset, String cleanup){ + public static GeneratorMapping create(String setup, String eval, String reset, String cleanup){ return new GeneratorMapping(setup, eval, reset, cleanup); } - + public String getMethodName(BlockType type){ switch(type){ case CLEANUP: @@ -76,6 +76,6 @@ public class GeneratorMapping { throw new IllegalStateException(); } } - - + + } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/MappingSet.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/MappingSet.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/MappingSet.java index ac0e413..80aaae8 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/MappingSet.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/MappingSet.java @@ -42,6 +42,10 @@ public class MappingSet { this("inIndex", "outIndex", new GeneratorMapping[] { mapping, mapping }); } + public boolean hasEmbeddedConstant(){ + return constant == current; + } + public MappingSet(String readIndex, String writeIndex, String workspaceIndex, String incoming, String outgoing, String workspace, GeneratorMapping... mappings) { this(readIndex, writeIndex, incoming, outgoing, mappings); http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/SignatureHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/SignatureHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/SignatureHolder.java index 536370b..d397acc 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/SignatureHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/SignatureHolder.java @@ -31,13 +31,15 @@ import com.google.common.collect.Maps; public class SignatureHolder implements Iterable<CodeGeneratorMethod>{ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SignatureHolder.class); - + private final Class<?> signature; private final CodeGeneratorMethod[] methods; private final Map<String, Integer> methodMap; private final SignatureHolder[] childHolders; - - + + public static final String DRILL_INIT_METHOD = "__DRILL_INIT__"; + public static final CodeGeneratorMethod DRILL_INIT = new CodeGeneratorMethod(DRILL_INIT_METHOD, void.class); + public static SignatureHolder getHolder(Class<?> signature){ List<SignatureHolder> innerClasses = Lists.newArrayList(); for(Class<?> inner : signature.getClasses()){ @@ -46,36 +48,39 @@ public class SignatureHolder implements Iterable<CodeGeneratorMethod>{ } return new SignatureHolder(signature, innerClasses.toArray(new SignatureHolder[innerClasses.size()])); } - + private SignatureHolder(Class<?> signature, SignatureHolder[] childHolders){ this.childHolders = childHolders; this.signature = signature; - Map<String, Integer> newMap = Maps.newHashMap(); - + Map<String, Integer> newMap = Maps.newHashMap(); + List<CodeGeneratorMethod> methodHolders = Lists.newArrayList(); Method[] reflectMethods = signature.getDeclaredMethods(); - + for(Method m : reflectMethods){ if( (m.getModifiers() & Modifier.ABSTRACT) == 0 && m.getAnnotation(RuntimeOverridden.class) == null) continue; methodHolders.add(new CodeGeneratorMethod(m)); } - - methods = new CodeGeneratorMethod[methodHolders.size()]; + + methods = new CodeGeneratorMethod[methodHolders.size()+1]; for(int i =0; i < methodHolders.size(); i++){ methods[i] = methodHolders.get(i); Integer old = newMap.put(methods[i].getMethodName(), i); if(old != null) throw new IllegalStateException(String.format("Attempting to add a method with name %s when there is already one method of that name in this class that is set to be runtime generated.", methods[i].getMethodName())); - + } + methods[methodHolders.size()] = DRILL_INIT; + newMap.put(DRILL_INIT.getMethodName(), methodHolders.size()); + methodMap = ImmutableMap.copyOf(newMap); } - + public Class<?> getSignatureClass(){ return signature; } - + public CodeGeneratorMethod get(int i){ return methods[i]; } @@ -84,12 +89,12 @@ public class SignatureHolder implements Iterable<CodeGeneratorMethod>{ public Iterator<CodeGeneratorMethod> iterator() { return Iterators.forArray(methods); } - + public int size(){ return methods.length; } - - + + public SignatureHolder[] getChildHolders() { return childHolders; } @@ -109,6 +114,6 @@ public class SignatureHolder implements Iterable<CodeGeneratorMethod>{ return "SignatureHolder [methods=" + (methods != null ? Arrays.asList(methods).subList(0, Math.min(methods.length, maxLen)) : null) + "]"; } - - + + } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ClassGenerator.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ClassGenerator.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ClassGenerator.java index 4d4fc99..69d68bb 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ClassGenerator.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ClassGenerator.java @@ -275,7 +275,7 @@ public class ClassGenerator<T>{ for(ClassGenerator<T> child : innerClasses.values()) { child.flushCode(); - } + } } public JCodeModel getModel() { @@ -405,6 +405,10 @@ public class ClassGenerator<T>{ return this; } + public JFieldRef f(String name){ + return holder.ref(name); + } + public boolean isConstant() { return this.isConstant; } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CodeGenerator.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CodeGenerator.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CodeGenerator.java index 658c63c..73c5980 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CodeGenerator.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CodeGenerator.java @@ -32,10 +32,10 @@ import com.sun.codemodel.JDefinedClass; * A code generator is responsible for generating the Java source code required to complete the implementation of an * abstract template. It is used with a class transformer to merge precompiled template code with runtime generated and * compiled query specific code to create a runtime instance. - * + * * A code generator can contain one or more ClassGenerators that implement outer and inner classes associated with a * particular runtime generated instance. - * + * * @param <T> * The interface that results from compiling and merging the runtime code that is generated. */ @@ -46,8 +46,11 @@ public class CodeGenerator<T> { private final TemplateClassDefinition<T> definition; private final String className; private final String fqcn; + private final JCodeModel model; private final ClassGenerator<T> rootGenerator; + private String generatedCode; + private String generifiedCode; CodeGenerator(TemplateClassDefinition<T> definition, FunctionImplementationRegistry funcRegistry) { this(ClassGenerator.getDefaultMapping(), definition, funcRegistry); @@ -74,12 +77,24 @@ public class CodeGenerator<T> { return rootGenerator; } - public String generate() throws IOException { + public void generate() throws IOException { rootGenerator.flushCode(); SingleClassStringWriter w = new SingleClassStringWriter(); model.build(w); - return w.getCode().toString(); + + this.generatedCode = w.getCode().toString(); + this.generifiedCode = generatedCode.replaceAll(this.className, "GenericGenerated"); + + } + + public String generateAndGet() throws IOException { + generate(); + return generatedCode; + } + + public String getGeneratedCode(){ + return generatedCode; } public TemplateClassDefinition<T> getDefinition() { @@ -99,15 +114,49 @@ public class CodeGenerator<T> { FunctionImplementationRegistry funcRegistry){ return get(definition, funcRegistry).getRoot(); } - + public static <T> ClassGenerator<T> getRoot(MappingSet mappingSet, TemplateClassDefinition<T> definition, FunctionImplementationRegistry funcRegistry){ return get(mappingSet, definition, funcRegistry).getRoot(); } - + public static <T> CodeGenerator<T> get(MappingSet mappingSet, TemplateClassDefinition<T> definition, FunctionImplementationRegistry funcRegistry) { return new CodeGenerator<T>(mappingSet, definition, funcRegistry); } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((definition == null) ? 0 : definition.hashCode()); + result = prime * result + ((generatedCode == null) ? 0 : generatedCode.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CodeGenerator other = (CodeGenerator) obj; + if (definition == null) { + if (other.definition != null) + return false; + } else if (!definition.equals(other.definition)) + return false; + if (generatedCode == null) { + if (other.generatedCode != null) + return false; + } else if (!generatedCode.equals(other.generatedCode)) + return false; + return true; + } + + + + } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java index caf9179..cf39246 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java @@ -17,6 +17,7 @@ */ package org.apache.drill.exec.expr; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -80,7 +81,13 @@ public class EvaluationVisitor { } public HoldingContainer addExpr(LogicalExpression e, ClassGenerator<?> generator) { - Set<LogicalExpression> constantBoundaries = ConstantExpressionIdentifier.getConstantExpressionSet(e); + + Set<LogicalExpression> constantBoundaries; + if(generator.getMappingSet().hasEmbeddedConstant()){ + constantBoundaries = Collections.emptySet(); + }else{ + constantBoundaries = ConstantExpressionIdentifier.getConstantExpressionSet(e); + } return e.accept(new ConstantFilter(constantBoundaries), generator); } @@ -93,17 +100,17 @@ public class EvaluationVisitor { } @Override - public HoldingContainer visitBooleanOperator(BooleanOperator op, + public HoldingContainer visitBooleanOperator(BooleanOperator op, ClassGenerator<?> generator) throws RuntimeException { if (op.getName().equals("booleanAnd")) { return visitBooleanAnd(op, generator); }else if(op.getName().equals("booleanOr")) { - return visitBooleanOr(op, generator); + return visitBooleanOr(op, generator); } else { throw new UnsupportedOperationException("BooleanOperator can only be booleanAnd, booleanOr. You are using " + op.getName()); } } - + @Override public HoldingContainer visitFunctionHolderExpression(FunctionHolderExpression holderExpr, ClassGenerator<?> generator) throws RuntimeException { @@ -290,16 +297,9 @@ public class EvaluationVisitor { return outputContainer; } } else { - String setMethod = e.isSafe() ? "setSafe" : "set"; - String isSafeMethod = "isSafe"; - - JInvocation setMeth; - if (Types.usesHolderForGet(inputContainer.getMajorType())) { - setMeth = vv.invoke("getMutator").invoke(setMethod).arg(outIndex).arg(inputContainer.getHolder()); - } else { - setMeth = vv.invoke("getMutator").invoke(setMethod).arg(outIndex).arg(inputContainer.getValue()); - } + final JInvocation setMeth = GetSetVectorHelper.write(e.getChild().getMajorType(), vv, inputContainer, outIndex, e.isSafe() ? "setSafe" : "set"); + final String isSafeMethod = "isSafe"; if (e.isSafe()) { HoldingContainer outputContainer = generator.declare(Types.REQUIRED_BIT); @@ -356,24 +356,9 @@ public class EvaluationVisitor { } if (!hasReadPath && !complex) { - JInvocation getValueAccessor = vv1.invoke("getAccessor").invoke("get"); - JInvocation getValueAccessor2 = vv1.invoke("getAccessor"); JBlock eval = new JBlock(); - - if (primitive) { - eval.assign(out.getValue(), getValueAccessor.arg(indexVariable)); - } else { - eval.add(getValueAccessor.arg(indexVariable).arg(out.getHolder())); - } - - if (out.isOptional()) { - JBlock blk = generator.getEvalBlock(); - blk.assign(out.getIsSet(), getValueAccessor2.invoke("isSet").arg(indexVariable)); - JConditional jc = blk._if(out.getIsSet().eq(JExpr.lit(1))); - jc._then().add(eval); - } else { - generator.getEvalBlock().add(eval); - } + GetSetVectorHelper.read(e.getMajorType(), vv1, eval, out, generator.getModel(), indexVariable); + generator.getEvalBlock().add(eval); } else { JExpression vector = e.isSuperReader() ? vv1.component(componentVariable) : vv1; @@ -419,7 +404,7 @@ public class EvaluationVisitor { JBlock ifNoVal = eval._if(desiredIndex.ne(currentIndex))._then().block(); if (out.isOptional()) { ifNoVal.assign(out.getIsSet(), JExpr.lit(0)); - } + } ifNoVal.assign(isNull, JExpr.lit(1)); ifNoVal._break(label); @@ -503,8 +488,9 @@ public class EvaluationVisitor { JType holderType = generator.getHolderType(majorType); JVar var = generator.declareClassField("string", holderType); JExpression stringLiteral = JExpr.lit(e.value); + JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer"); setup.assign(var, - generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getVarCharHolder").arg(stringLiteral)); + generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getVarCharHolder").arg(buffer).arg(stringLiteral)); return new HoldingContainer(majorType, var, null, null); } @@ -601,20 +587,20 @@ public class EvaluationVisitor { FunctionCall fc = new FunctionCall(convertFunctionName, newArgs, e.getPosition()); return fc.accept(this, value); } - + private HoldingContainer visitBooleanAnd(BooleanOperator op, ClassGenerator<?> generator) { - + HoldingContainer out = generator.declare(op.getMajorType()); - + JLabel label = generator.getEvalBlockLabel("AndOP"); JBlock eval = generator.getEvalBlock().block(); // enter into nested block generator.nestEvalBlock(eval); HoldingContainer arg = null; - + JExpression e = null; - + // value of boolean "and" when one side is null // p q p and q // true null null @@ -624,57 +610,57 @@ public class EvaluationVisitor { // null null null for (int i = 0; i < op.args.size(); i++) { arg = op.args.get(i).accept(this, generator); - + JBlock earlyExit = null; if (arg.isOptional()) { - earlyExit = eval._if(arg.getIsSet().eq(JExpr.lit(1)).cand(arg.getValue().ne(JExpr.lit(1))))._then(); + earlyExit = eval._if(arg.getIsSet().eq(JExpr.lit(1)).cand(arg.getValue().ne(JExpr.lit(1))))._then(); if(e == null){ e = arg.getIsSet(); }else{ e = e.mul(arg.getIsSet()); - } + } } else { - earlyExit = eval._if(arg.getValue().ne(JExpr.lit(1)))._then(); + earlyExit = eval._if(arg.getValue().ne(JExpr.lit(1)))._then(); } - + if (out.isOptional()) { earlyExit.assign(out.getIsSet(), JExpr.lit(1)); - } - - earlyExit.assign(out.getValue(), JExpr.lit(0)); - earlyExit._break(label); + } + + earlyExit.assign(out.getValue(), JExpr.lit(0)); + earlyExit._break(label); } - + if (out.isOptional()) { assert (e != null); - + JConditional notSetJC = eval._if(e.eq(JExpr.lit(0))); notSetJC._then().assign(out.getIsSet(), JExpr.lit(0)); - + JBlock setBlock = notSetJC._else().block(); setBlock.assign(out.getIsSet(), JExpr.lit(1)); setBlock.assign(out.getValue(), JExpr.lit(1)); } else { - assert (e == null); + assert (e == null); eval.assign(out.getValue(), JExpr.lit(1)) ; } - - generator.unNestEvalBlock(); // exit from nested block - + + generator.unNestEvalBlock(); // exit from nested block + return out; } - + private HoldingContainer visitBooleanOr(BooleanOperator op, ClassGenerator<?> generator) { - + HoldingContainer out = generator.declare(op.getMajorType()); - + JLabel label = generator.getEvalBlockLabel("OrOP"); JBlock eval = generator.getEvalBlock().block(); - generator.nestEvalBlock(eval); // enter into nested block. + generator.nestEvalBlock(eval); // enter into nested block. HoldingContainer arg = null; - + JExpression e = null; // value of boolean "or" when one side is null @@ -684,49 +670,49 @@ public class EvaluationVisitor { // null true true // null false null // null null null - + for (int i = 0; i < op.args.size(); i++) { arg = op.args.get(i).accept(this, generator); - + JBlock earlyExit = null; if (arg.isOptional()) { - earlyExit = eval._if(arg.getIsSet().eq(JExpr.lit(1)).cand(arg.getValue().eq(JExpr.lit(1))))._then(); + earlyExit = eval._if(arg.getIsSet().eq(JExpr.lit(1)).cand(arg.getValue().eq(JExpr.lit(1))))._then(); if(e == null){ e = arg.getIsSet(); }else{ e = e.mul(arg.getIsSet()); - } + } } else { - earlyExit = eval._if(arg.getValue().eq(JExpr.lit(1)))._then(); + earlyExit = eval._if(arg.getValue().eq(JExpr.lit(1)))._then(); } - + if (out.isOptional()) { earlyExit.assign(out.getIsSet(), JExpr.lit(1)); - } - - earlyExit.assign(out.getValue(), JExpr.lit(1)); - earlyExit._break(label); + } + + earlyExit.assign(out.getValue(), JExpr.lit(1)); + earlyExit._break(label); } - + if (out.isOptional()) { assert (e != null); - + JConditional notSetJC = eval._if(e.eq(JExpr.lit(0))); notSetJC._then().assign(out.getIsSet(), JExpr.lit(0)); - + JBlock setBlock = notSetJC._else().block(); setBlock.assign(out.getIsSet(), JExpr.lit(1)); setBlock.assign(out.getValue(), JExpr.lit(0)); } else { - assert (e == null); + assert (e == null); eval.assign(out.getValue(), JExpr.lit(0)) ; } - - generator.unNestEvalBlock(); // exit from nested block. - + + generator.unNestEvalBlock(); // exit from nested block. + return out; } - + } private class ConstantFilter extends EvalVisitor { http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java new file mode 100644 index 0000000..46bd7f0 --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java @@ -0,0 +1,175 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.drill.exec.expr; + +import io.netty.buffer.DrillBuf; + +import org.apache.drill.common.types.TypeProtos.MajorType; +import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; + +import com.sun.codemodel.JBlock; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JExpr; +import com.sun.codemodel.JExpression; +import com.sun.codemodel.JInvocation; +import com.sun.codemodel.JVar; + +public class GetSetVectorHelper { + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(GetSetVectorHelper.class); + + // eval.add(getValueAccessor.arg(indexVariable).arg(out.getHolder())); + + public static void read(MajorType type, JExpression vector, JBlock eval, HoldingContainer out, JCodeModel model, + JExpression indexVariable) { + + JInvocation getValueAccessor = vector.invoke("getAccessor"); + + switch(type.getMode()){ + case OPTIONAL: + eval.assign(out.getIsSet(), getValueAccessor.invoke("isSet").arg(indexVariable)); + eval = eval._if(out.getIsSet().eq(JExpr.lit(1)))._then(); + + // fall through + case REQUIRED: + switch (type.getMinorType()) { + case BIGINT: + case FLOAT4: + case FLOAT8: + case INT: + case MONEY: + case SMALLINT: + case TINYINT: + case UINT1: + case UINT2: + case UINT4: + case UINT8: + case INTERVALYEAR: + case DATE: + case TIME: + case TIMESTAMP: + case BIT: + eval.assign(out.getValue(), getValueAccessor.invoke("get").arg(indexVariable)); + return; + case DECIMAL9: + case DECIMAL18: + eval.assign(out.getHolder().ref("scale"), vector.invoke("getField").invoke("getScale")); + eval.assign(out.getHolder().ref("precision"), vector.invoke("getField").invoke("getPrecision")); + eval.assign(out.getValue(), getValueAccessor.invoke("get").arg(indexVariable)); + return; + case DECIMAL28DENSE: + case DECIMAL28SPARSE: + case DECIMAL38DENSE: + case DECIMAL38SPARSE: + eval.assign(out.getHolder().ref("scale"), vector.invoke("getField").invoke("getScale")); + eval.assign(out.getHolder().ref("precision"), vector.invoke("getField").invoke("getPrecision")); + eval.assign(out.getHolder().ref("start"), JExpr.lit(TypeHelper.getSize(type)).mul(indexVariable)); + eval.assign(out.getHolder().ref("buffer"), vector.invoke("getData")); + return; + case INTERVAL:{ + JVar start = eval.decl(model.INT, "start", JExpr.lit(TypeHelper.getSize(type)).mul(indexVariable)); + JVar data = eval.decl(model.ref(DrillBuf.class), "data", vector.invoke("getData")); + eval.assign(out.getHolder().ref("months"), data.invoke("getInt").arg(start)); + eval.assign(out.getHolder().ref("days"), data.invoke("getInt").arg(start.plus(JExpr.lit(4)))); + eval.assign(out.getHolder().ref("milliseconds"), data.invoke("getInt").arg(start.plus(JExpr.lit(8)))); + return; + } + case INTERVALDAY: { + JVar start = eval.decl(model.INT, "start", JExpr.lit(TypeHelper.getSize(type)).mul(indexVariable)); + eval.assign(out.getHolder().ref("days"), vector.invoke("getData").invoke("getInt").arg(start)); + eval.assign(out.getHolder().ref("milliseconds"), vector.invoke("getData").invoke("getInt").arg(start.plus(JExpr.lit(4)))); + return; + } + case VAR16CHAR: + case VARBINARY: + case VARCHAR: + eval.assign(out.getHolder().ref("buffer"), vector.invoke("getData")); + JVar se = eval.decl(model.LONG, "startEnd", getValueAccessor.invoke("getStartEnd").arg(indexVariable)); + eval.assign(out.getHolder().ref("start"), JExpr.cast(model._ref(int.class), se)); + eval.assign(out.getHolder().ref("end"), JExpr.cast(model._ref(int.class), se.shr(JExpr.lit(32)))); + return; + + } + } + + // fallback. + eval.add(getValueAccessor.invoke("get").arg(indexVariable).arg(out.getHolder())); + } + + public static JInvocation write(MajorType type, JVar vector, HoldingContainer in, JExpression indexVariable, String setMethodName) { + + JInvocation setMethod = vector.invoke("getMutator").invoke(setMethodName).arg(indexVariable); + + switch(type.getMode()){ + case OPTIONAL: + setMethod = setMethod.arg(in.f("isSet")); + case REQUIRED: + switch (type.getMinorType()) { + case BIGINT: + case FLOAT4: + case FLOAT8: + case INT: + case MONEY: + case SMALLINT: + case TINYINT: + case UINT1: + case UINT2: + case UINT4: + case UINT8: + case INTERVALYEAR: + case DATE: + case TIME: + case TIMESTAMP: + case BIT: + case DECIMAL9: + case DECIMAL18: + return setMethod // + .arg(in.getValue()); + case DECIMAL28DENSE: + case DECIMAL28SPARSE: + case DECIMAL38DENSE: + case DECIMAL38SPARSE: + return setMethod // + .arg(in.f("start")) // + .arg(in.f("buffer")); + case INTERVAL:{ + return setMethod // + .arg(in.f("months")) // + .arg(in.f("days")) // + .arg(in.f("milliseconds")); + } + case INTERVALDAY: { + return setMethod // + .arg(in.f("days")) // + .arg(in.f("milliseconds")); + } + case VAR16CHAR: + case VARBINARY: + case VARCHAR: + return setMethod // + .arg(in.f("start")) // + .arg(in.f("end")) // + .arg(in.f("buffer")); + } + } + + + return setMethod.arg(in.getHolder()); + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java index 989e490..5281c37 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java @@ -45,7 +45,7 @@ import com.sun.codemodel.JVar; class DrillAggFuncHolder extends DrillFuncHolder{ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillAggFuncHolder.class); - + private final String setup; private final String reset; private final String add; @@ -57,7 +57,7 @@ class DrillAggFuncHolder extends DrillFuncHolder{ Map<String, String> methods, List<String> imports) { this(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports, FunctionCostCategory.getDefault()); } - + public DrillAggFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, Map<String, String> methods, List<String> imports, FunctionCostCategory costCategory) { @@ -84,38 +84,38 @@ class DrillAggFuncHolder extends DrillFuncHolder{ @Override public JVar[] renderStart(ClassGenerator<?> g, HoldingContainer[] inputVariables) { - if (!g.getMappingSet().isHashAggMapping()) { //Declare workspace vars for non-hash-aggregation. + if (!g.getMappingSet().isHashAggMapping()) { //Declare workspace vars for non-hash-aggregation. JVar[] workspaceJVars = declareWorkspaceVariables(g); - generateBody(g, BlockType.SETUP, setup, null, workspaceJVars, false); + generateBody(g, BlockType.SETUP, setup, null, workspaceJVars, true); return workspaceJVars; } else { //Declare workspace vars and workspace vectors for hash aggregation. - + JVar[] workspaceJVars = declareWorkspaceVectors(g); - + JBlock setupBlock = g.getSetupBlock(); - - //Loop through all workspace vectors, to get the minimum of size of all workspace vectors. + + //Loop through all workspace vectors, to get the minimum of size of all workspace vectors. JVar sizeVar = setupBlock.decl(g.getModel().INT, "vectorSize", JExpr.lit(Integer.MAX_VALUE)); JClass mathClass = g.getModel().ref(Math.class); for (int id = 0; id<workspaceVars.length; id ++) { setupBlock.assign(sizeVar,mathClass.staticInvoke("min").arg(sizeVar).arg(g.getWorkspaceVectors().get(workspaceVars[id]).invoke("getValueCapacity"))); } - - for(int i =0 ; i < workspaceVars.length; i++) { + + for(int i =0 ; i < workspaceVars.length; i++) { setupBlock.assign(workspaceJVars[i], JExpr._new(g.getHolderType(workspaceVars[i].majorType))); } - - //Use for loop to initialize entries in the workspace vectors. + + //Use for loop to initialize entries in the workspace vectors. JForLoop forLoop = setupBlock._for(); JVar ivar = forLoop.init(g.getModel().INT, "drill_internal_i", JExpr.lit(0)); forLoop.test(ivar.lt(sizeVar)); forLoop.update(ivar.assignPlus(JExpr.lit(1))); - + JBlock subBlock = generateInitWorkspaceBlockHA(g, BlockType.SETUP, setup, workspaceJVars, ivar); forLoop.body().add(subBlock); - return workspaceJVars; + return workspaceJVars; } - + } @@ -134,7 +134,7 @@ class DrillAggFuncHolder extends DrillFuncHolder{ JVar internalOutput = sub.decl(JMod.FINAL, g.getHolderType(returnValue.type), returnValue.name, JExpr._new(g.getHolderType(returnValue.type))); addProtectedBlock(g, sub, output, null, workspaceJVars, false); sub.assign(out.getHolder(), internalOutput); - //hash aggregate uses workspace vectors. Initialization is done in "setup" and does not require "reset" block. + //hash aggregate uses workspace vectors. Initialization is done in "setup" and does not require "reset" block. if (!g.getMappingSet().isHashAggMapping()) { generateBody(g, BlockType.RESET, reset, null, workspaceJVars, false); } @@ -146,27 +146,27 @@ class DrillAggFuncHolder extends DrillFuncHolder{ private JVar[] declareWorkspaceVectors(ClassGenerator<?> g) { JVar[] workspaceJVars = new JVar[workspaceVars.length]; - + for(int i =0 ; i < workspaceVars.length; i++){ Preconditions.checkState(Types.isFixedWidthType(workspaceVars[i].majorType), String.format("Workspace variable '%s' in aggregation function '%s' is not allowed to have variable length type.", workspaceVars[i].name, registeredNames[0])); Preconditions.checkState(workspaceVars[i].majorType.getMode()==DataMode.REQUIRED, String.format("Workspace variable '%s' in aggregation function '%s' is not allowed to have null or repeated type.", workspaceVars[i].name, registeredNames[0])); //workspaceJVars[i] = g.declareClassField("work", g.getHolderType(workspaceVars[i].majorType), JExpr._new(g.getHolderType(workspaceVars[i].majorType))); - workspaceJVars[i] = g.declareClassField("work", g.getHolderType(workspaceVars[i].majorType)); - + workspaceJVars[i] = g.declareClassField("work", g.getHolderType(workspaceVars[i].majorType)); + //Declare a workspace vector for the workspace var. TypedFieldId typedFieldId = new TypedFieldId(workspaceVars[i].majorType, g.getWorkspaceTypes().size()); JVar vv = g.declareVectorValueSetupAndMember(g.getMappingSet().getWorkspace(), typedFieldId); - + g.getWorkspaceTypes().add(typedFieldId); g.getWorkspaceVectors().put(workspaceVars[i], vv); } return workspaceJVars; } - + private JBlock generateInitWorkspaceBlockHA(ClassGenerator<?> g, BlockType bt, String body, JVar[] workspaceJVars, JExpression wsIndexVariable){ JBlock initBlock = new JBlock(true, true); - if(!Strings.isNullOrEmpty(body) && !body.trim().isEmpty()){ + if(!Strings.isNullOrEmpty(body) && !body.trim().isEmpty()){ JBlock sub = new JBlock(true, true); addProtectedBlockHA(g, sub, body, null, workspaceJVars, wsIndexVariable); initBlock.directStatement(String.format("/** start %s for function %s **/ ", bt.name(), registeredNames[0])); @@ -175,51 +175,51 @@ class DrillAggFuncHolder extends DrillFuncHolder{ } return initBlock; } - + @Override protected void addProtectedBlock(ClassGenerator<?> g, JBlock sub, String body, HoldingContainer[] inputVariables, JVar[] workspaceJVars, boolean decConstantInputOnly){ if (!g.getMappingSet().isHashAggMapping()) { super.addProtectedBlock(g, sub, body, inputVariables, workspaceJVars, decConstantInputOnly); } else { JExpression indexVariable = g.getMappingSet().getWorkspaceIndex(); - addProtectedBlockHA(g, sub, body, inputVariables, workspaceJVars, indexVariable); + addProtectedBlockHA(g, sub, body, inputVariables, workspaceJVars, indexVariable); } } /* - * This is customized version of "addProtectedBlock" for hash aggregation. It take one additional parameter "wsIndexVariable". + * This is customized version of "addProtectedBlock" for hash aggregation. It take one additional parameter "wsIndexVariable". */ private void addProtectedBlockHA(ClassGenerator<?> g, JBlock sub, String body, HoldingContainer[] inputVariables, JVar[] workspaceJVars, JExpression wsIndexVariable){ if (inputVariables != null){ for(int i =0; i < inputVariables.length; i++){ ValueReference parameter = parameters[i]; HoldingContainer inputVariable = inputVariables[i]; - sub.decl(inputVariable.getHolder().type(), parameter.name, inputVariable.getHolder()); + sub.decl(inputVariable.getHolder().type(), parameter.name, inputVariable.getHolder()); } } - JVar[] internalVars = new JVar[workspaceJVars.length]; + JVar[] internalVars = new JVar[workspaceJVars.length]; for(int i =0; i < workspaceJVars.length; i++){ //sub.assign(workspaceJVars[i], JExpr._new(g.getHolderType(workspaceVars[i].majorType))); - //Access workspaceVar through workspace vector. - JInvocation getValueAccessor = g.getWorkspaceVectors().get(workspaceVars[i]).invoke("getAccessor").invoke("get"); + //Access workspaceVar through workspace vector. + JInvocation getValueAccessor = g.getWorkspaceVectors().get(workspaceVars[i]).invoke("getAccessor").invoke("get"); if (Types.usesHolderForGet(workspaceVars[i].majorType)) { sub.add(getValueAccessor.arg(wsIndexVariable).arg(workspaceJVars[i])); } else { sub.assign(workspaceJVars[i].ref("value"), getValueAccessor.arg(wsIndexVariable)); } - internalVars[i] = sub.decl(g.getHolderType(workspaceVars[i].majorType), workspaceVars[i].name, workspaceJVars[i]); + internalVars[i] = sub.decl(g.getHolderType(workspaceVars[i].majorType), workspaceVars[i].name, workspaceJVars[i]); } - + Preconditions.checkNotNull(body); sub.directStatement(body); JVar successVar = sub.decl(JType.parse(g.getModel(), "boolean"), "success", JExpr.lit(false)); - + // reassign workspace variables back. for(int i =0; i < workspaceJVars.length; i++){ sub.assign(workspaceJVars[i], internalVars[i]); - - //Change workspaceVar through workspace vector. + + //Change workspaceVar through workspace vector. JInvocation setMeth; if (Types.usesHolderForGet(workspaceVars[i].majorType)) { setMeth = g.getWorkspaceVectors().get(workspaceVars[i]).invoke("getMutator").invoke("setSafe").arg(wsIndexVariable).arg(workspaceJVars[i]); @@ -233,7 +233,7 @@ class DrillAggFuncHolder extends DrillFuncHolder{ sub._if(successVar.eq(JExpr.lit(false)))._then()._throw(JExpr._new(drillRunTimeException).arg(JExpr.lit("setsafe() failed; cannot set holder value into the vector"))); } - + } } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalAddFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalAddFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalAddFuncHolder.java index 98c1c85..61e04ca 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalAddFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalAddFuncHolder.java @@ -23,12 +23,11 @@ import java.util.Map; import org.apache.drill.common.expression.LogicalExpression; import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.TypeProtos.MajorType; - import org.apache.drill.common.util.DecimalScalePrecisionAddFunction; import org.apache.drill.common.util.DecimalScalePrecisionDivideFunction; -import org.apache.drill.common.util.DecimalUtility; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; +import org.apache.drill.exec.util.DecimalUtility; public class DrillDecimalAddFuncHolder extends DrillSimpleFuncHolder{ http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalDivScaleFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalDivScaleFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalDivScaleFuncHolder.java index 941dc49..c3a23e7 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalDivScaleFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalDivScaleFuncHolder.java @@ -23,11 +23,10 @@ import java.util.Map; import org.apache.drill.common.expression.LogicalExpression; import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.TypeProtos.MajorType; - import org.apache.drill.common.util.DecimalScalePrecisionDivideFunction; -import org.apache.drill.common.util.DecimalUtility; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; +import org.apache.drill.exec.util.DecimalUtility; public class DrillDecimalDivScaleFuncHolder extends DrillSimpleFuncHolder{ http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java index 2cf1088..621e1dd 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalModScaleFuncHolder.java @@ -23,12 +23,11 @@ import java.util.Map; import org.apache.drill.common.expression.LogicalExpression; import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.TypeProtos.MajorType; - import org.apache.drill.common.util.DecimalScalePrecisionDivideFunction; import org.apache.drill.common.util.DecimalScalePrecisionModFunction; -import org.apache.drill.common.util.DecimalUtility; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; +import org.apache.drill.exec.util.DecimalUtility; public class DrillDecimalModScaleFuncHolder extends DrillSimpleFuncHolder{ http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalSumScaleFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalSumScaleFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalSumScaleFuncHolder.java index 6c04afc..cb8bfed 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalSumScaleFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillDecimalSumScaleFuncHolder.java @@ -23,11 +23,10 @@ import java.util.Map; import org.apache.drill.common.expression.LogicalExpression; import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.TypeProtos.MajorType; - import org.apache.drill.common.util.DecimalScalePrecisionMulFunction; -import org.apache.drill.common.util.DecimalUtility; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; +import org.apache.drill.exec.util.DecimalUtility; public class DrillDecimalSumScaleFuncHolder extends DrillSimpleFuncHolder{ http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java index 5ca48ce..fcc0b35 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java @@ -28,6 +28,8 @@ import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.TypeProtos.MajorType; import org.apache.drill.common.types.TypeProtos.MinorType; import org.apache.drill.common.types.Types; +import org.apache.drill.exec.compile.bytecode.ScalarReplacementTypes; +import org.apache.drill.exec.compile.sig.SignatureHolder; import org.apache.drill.exec.expr.ClassGenerator; import org.apache.drill.exec.expr.ClassGenerator.BlockType; import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; @@ -114,10 +116,26 @@ public abstract class DrillFuncHolder extends AbstractFuncHolder { return isRandom; } + protected JVar[] declareWorkspaceVariables(ClassGenerator<?> g) { JVar[] workspaceJVars = new JVar[workspaceVars.length]; for (int i = 0; i < workspaceVars.length; i++) { - workspaceJVars[i] = g.declareClassField("work", g.getModel()._ref(workspaceVars[i].type)); + WorkspaceReference ref = workspaceVars[i]; + JType jtype = g.getModel()._ref(ref.type); + + if(ScalarReplacementTypes.CLASSES.contains(ref.type)){ + workspaceJVars[i] = g.declareClassField("work", jtype); + JBlock b = g.getBlock(SignatureHolder.DRILL_INIT_METHOD); + b.assign(workspaceJVars[i], JExpr._new(jtype)); + }else{ + workspaceJVars[i] = g.declareClassField("work", jtype); + } + + if(ref.isInject()){ + g.getBlock(BlockType.SETUP).assign(workspaceJVars[i], g.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer")); + }else{ + //g.getBlock(BlockType.SETUP).assign(workspaceJVars[i], JExpr._new(jtype)); + } } return workspaceJVars; } @@ -159,7 +177,13 @@ public abstract class DrillFuncHolder extends AbstractFuncHolder { JVar[] internalVars = new JVar[workspaceJVars.length]; for (int i = 0; i < workspaceJVars.length; i++) { - internalVars[i] = sub.decl(g.getModel()._ref(workspaceVars[i].type), workspaceVars[i].name, workspaceJVars[i]); + if(decConstInputOnly){ + internalVars[i] = sub.decl(g.getModel()._ref(workspaceVars[i].type), workspaceVars[i].name, workspaceJVars[i]); + }else{ + + internalVars[i] = sub.decl(g.getModel()._ref(workspaceVars[i].type), workspaceVars[i].name, workspaceJVars[i]); + } + } Preconditions.checkNotNull(body); @@ -303,19 +327,24 @@ public abstract class DrillFuncHolder extends AbstractFuncHolder { Class<?> type; String name; MajorType majorType; + boolean inject; - public WorkspaceReference(Class<?> type, String name) { + public WorkspaceReference(Class<?> type, String name, boolean inject) { super(); Preconditions.checkNotNull(type); Preconditions.checkNotNull(name); this.type = type; this.name = name; + this.inject = inject; } void setMajorType(MajorType majorType) { this.majorType = majorType; } + public boolean isInject(){ + return inject; + } } public boolean checkPrecisionRange() { http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java index 64f45c7..63ddb11 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java @@ -17,6 +17,8 @@ */ package org.apache.drill.exec.expr.fn; +import io.netty.buffer.DrillBuf; + import java.io.IOException; import java.io.InputStream; import java.io.StringReader; @@ -25,6 +27,8 @@ import java.net.URL; import java.util.List; import java.util.Map; +import javax.inject.Inject; + import org.apache.drill.common.types.TypeProtos.MajorType; import org.apache.drill.common.util.FileUtils; import org.apache.drill.exec.expr.DrillFunc; @@ -111,15 +115,17 @@ public class FunctionConverter { Param param = field.getAnnotation(Param.class); Output output = field.getAnnotation(Output.class); Workspace workspace = field.getAnnotation(Workspace.class); + Inject inject = field.getAnnotation(Inject.class); int i =0; if(param != null) i++; if(output != null) i++; if(workspace != null) i++; + if(inject != null) i++; if(i == 0){ - return failure("The field must be either a @Param, @Output or @Workspace field.", clazz, field); + return failure("The field must be either a @Param, @Output, @Inject or @Workspace field.", clazz, field); }else if(i > 1){ - return failure("The field must be only one of @Param, @Output or @Workspace. It currently has more than one of these annotations.", clazz, field); + return failure("The field must be only one of @Param, @Output, @Inject or @Workspace. It currently has more than one of these annotations.", clazz, field); } if(param != null || output != null){ @@ -132,7 +138,7 @@ public class FunctionConverter { // Special processing for @Output ComplexWriter if (output != null && ComplexWriter.class.isAssignableFrom(field.getType())) { - + if(outputField != null){ return failure("You've declared more than one @Output field. You must declare one and only @Output field per Function class.", clazz, field); }else{ @@ -140,7 +146,7 @@ public class FunctionConverter { } continue; } - + // check that param and output are value holders. if(!ValueHolder.class.isAssignableFrom(field.getType())){ return failure(String.format("The field doesn't holds value of type %s which does not implement the ValueHolder interface. All fields of type @Param or @Output must extend this interface..", field.getType()), clazz, field); @@ -168,12 +174,14 @@ public class FunctionConverter { outputField = p; } } - + }else{ // workspace work. - WorkspaceReference wsReference = new WorkspaceReference(field.getType(), field.getName()); + boolean isInject = inject != null; + if(isInject && !field.getType().equals(DrillBuf.class)) return failure(String.format("Only DrillBuf is allowed to be injected. You attempted to inject %s.", field.getType()), clazz, field); + WorkspaceReference wsReference = new WorkspaceReference(field.getType(), field.getName(), isInject); - if (template.scope() == FunctionScope.POINT_AGGREGATE && !ValueHolder.class.isAssignableFrom(field.getType()) ) { + if (!isInject && template.scope() == FunctionScope.POINT_AGGREGATE && !ValueHolder.class.isAssignableFrom(field.getType()) ) { return failure(String.format("Aggregate function '%s' workspace variable '%s' is of type '%s'. Please change it to Holder type.", template.name(), field.getName(), field.getType()), clazz, field); } @@ -229,21 +237,21 @@ public class FunctionConverter { template.isRandom(), registeredNames, ps, outputField, works, methods, imports); case SIMPLE: if (outputField.isComplexWriter) - return new DrillComplexWriterFuncHolder(template.scope(), template.nulls(), + return new DrillComplexWriterFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), - template.isRandom(), registeredNames, + template.isRandom(), registeredNames, ps, outputField, works, methods, imports); else - return new DrillSimpleFuncHolder(template.scope(), template.nulls(), + return new DrillSimpleFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), - template.isRandom(), registeredNames, + template.isRandom(), registeredNames, ps, outputField, works, methods, imports, template.costCategory()); case SC_BOOLEAN_OPERATOR: - return new DrillBooleanOPHolder(template.scope(), template.nulls(), + return new DrillBooleanOPHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), - template.isRandom(), registeredNames, + template.isRandom(), registeredNames, ps, outputField, works, methods, imports); - + case DECIMAL_MAX_SCALE: return new DrillDecimalMaxScaleFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), template.isRandom(), registeredNames, ps, outputField, works, methods, imports); http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ByteFunctionHelpers.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ByteFunctionHelpers.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ByteFunctionHelpers.java new file mode 100644 index 0000000..be1d9e6 --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ByteFunctionHelpers.java @@ -0,0 +1,96 @@ +/******************************************************************************* + + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package org.apache.drill.exec.expr.fn.impl; + +import com.google.common.primitives.UnsignedLongs; + +import io.netty.util.internal.PlatformDependent; + +public class ByteFunctionHelpers { + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ByteFunctionHelpers.class); + + public static final int equal(final long laddr, int lStart, int lEnd, final long raddr, int rStart, + final int rEnd) { + + int n = lEnd - lStart; + if (n == rEnd - rStart) { + long lPos = laddr + lStart; + long rPos = raddr + rStart; + + while (n > 7) { + long leftLong = PlatformDependent.getLong(lPos); + long rightLong = PlatformDependent.getLong(rPos); + if (leftLong != rightLong) { + return 0; + } + lPos += 8; + rPos += 8; + n -= 8; + } + while (n-- != 0) { + byte leftByte = PlatformDependent.getByte(lPos); + byte rightByte = PlatformDependent.getByte(rPos); + if (leftByte != rightByte) { + return 0; + } + lPos++; + rPos++; + } + return 1; + } else { + return 0; + } + } + + public static final int compare(final long laddr, int lStart, int lEnd, final long raddr, int rStart, final int rEnd) { + int lLen = lEnd - lStart; + int rLen = rEnd - rStart; + int n = Math.min(rLen, lLen); + long lPos = laddr + lStart; + long rPos = raddr + rStart; + + while (n > 7) { + long leftLong = PlatformDependent.getLong(lPos); + long rightLong = PlatformDependent.getLong(rPos); + if(leftLong != rightLong){ + return UnsignedLongs.compare(Long.reverseBytes(leftLong), Long.reverseBytes(rightLong)); + } + lPos += 8; + rPos += 8; + n -= 8; + } + + while (n-- != 0) { + byte leftByte = PlatformDependent.getByte(lPos); + byte rightByte = PlatformDependent.getByte(rPos); + if (leftByte != rightByte) { + return ((leftByte & 0xFF) - (rightByte & 0xFF)) > 0 ? 1 : -1; + } + lPos++; + rPos++; + } + + if (lLen == rLen) return 0; + + return lLen > rLen ? 1 : 0; + + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarBinaryToDate.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarBinaryToDate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarBinaryToDate.java new file mode 100644 index 0000000..2161bfd --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarBinaryToDate.java @@ -0,0 +1,43 @@ +/******************************************************************************* + + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package org.apache.drill.exec.expr.fn.impl; + +import org.apache.drill.exec.expr.DrillSimpleFunc; +import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; +import org.apache.drill.exec.expr.annotations.Output; +import org.apache.drill.exec.expr.annotations.Param; +import org.apache.drill.exec.expr.holders.DateHolder; +import org.apache.drill.exec.expr.holders.VarBinaryHolder; +import org.apache.drill.exec.record.RecordBatch; + +@FunctionTemplate(names = {"castDATE", "datetype"}, scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL, costCategory = FunctionCostCategory.COMPLEX) +public class CastVarBinaryToDate implements DrillSimpleFunc { + + @Param VarBinaryHolder in; + @Output DateHolder out; + + public void setup(RecordBatch incoming) { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.getDate(in.buffer.memoryAddress(), in.start, in.end); + } + } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarCharVar16Char.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarCharVar16Char.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarCharVar16Char.java index 12656d4..5280717 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarCharVar16Char.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CastVarCharVar16Char.java @@ -17,7 +17,12 @@ */ package org.apache.drill.exec.expr.fn.impl; -import io.netty.buffer.ByteBuf; +import io.netty.buffer.DrillBuf; + +import java.nio.charset.Charset; + +import javax.inject.Inject; + import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; @@ -29,8 +34,6 @@ import org.apache.drill.exec.expr.holders.Var16CharHolder; import org.apache.drill.exec.expr.holders.VarCharHolder; import org.apache.drill.exec.record.RecordBatch; -import java.nio.charset.Charset; - @SuppressWarnings("unused") @FunctionTemplate(names = {"castVAR16CHAR", "to_var16char", "to_string"}, scope = FunctionTemplate.FunctionScope.SIMPLE, nulls= NullHandling.NULL_IF_NULL) public class CastVarCharVar16Char implements DrillSimpleFunc { @@ -38,19 +41,18 @@ public class CastVarCharVar16Char implements DrillSimpleFunc { @Param BigIntHolder length; @Output Var16CharHolder out; @Workspace Charset charset; - @Workspace ByteBuf buffer; + @Inject DrillBuf buffer; @Override public void setup(RecordBatch incoming) { charset = java.nio.charset.Charset.forName("UTF-16"); - buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[65536]); } @Override public void eval() { //if input length <= target_type length, do nothing //else truncate based on target_type length - byte[] buf = in.toString().getBytes(charset); + byte[] buf = org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(in.start, in.end, in.buffer).getBytes(charset); buffer.setBytes(0, buf); out.start = 0; http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/DateTypeFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/DateTypeFunctions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/DateTypeFunctions.java index 725566f..f063466 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/DateTypeFunctions.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/DateTypeFunctions.java @@ -18,7 +18,9 @@ package org.apache.drill.exec.expr.fn.impl; -import io.netty.buffer.ByteBuf; +import io.netty.buffer.DrillBuf; + +import javax.inject.Inject; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; @@ -59,7 +61,7 @@ public class DateTypeFunctions { out.months = (int) ((inputYears.value * org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths) + (inputMonths.value)); out.days = (int) inputDays.value; - out.milliSeconds = (int) ((inputHours.value * org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis) + + out.milliseconds = (int) ((inputHours.value * org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis) + (inputMinutes.value * org.apache.drill.exec.expr.fn.impl.DateUtility.minutesToMillis) + (inputSeconds.value * org.apache.drill.exec.expr.fn.impl.DateUtility.secondsToMillis) + (inputMilliSeconds.value)); @@ -99,7 +101,7 @@ public class DateTypeFunctions { public void eval() { out.days = (int) inputDays.value; - out.milliSeconds = (int) ((inputHours.value * org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis) + + out.milliseconds = (int) ((inputHours.value * org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis) + (inputMinutes.value * org.apache.drill.exec.expr.fn.impl.DateUtility.minutesToMillis) + (inputSeconds.value * org.apache.drill.exec.expr.fn.impl.DateUtility.secondsToMillis) + (inputMillis.value)); @@ -174,7 +176,7 @@ public class DateTypeFunctions { public void eval() { - String timeZone = (inputTimeZone.toString()); + String timeZone = (org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(inputTimeZone.start, inputTimeZone.end, inputTimeZone.buffer)); out.value = ((new org.joda.time.MutableDateTime((int)inputYears.value, (int)inputMonths.value, (int)inputDays.value, @@ -268,11 +270,10 @@ public class DateTypeFunctions { @FunctionTemplate(name = "timeofday", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, isRandom = true) public static class TimeOfDay implements DrillSimpleFunc { - @Workspace ByteBuf buffer; + @Inject DrillBuf buffer; @Output VarCharHolder out; public void setup(RecordBatch incoming) { - buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[100]); } public void eval() { @@ -388,7 +389,7 @@ public class DateTypeFunctions { long days = diff / org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis; out.months = (int) (days / org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); out.days = (int) (days % org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); - out.milliSeconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); + out.milliseconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); } } @@ -411,7 +412,7 @@ public class DateTypeFunctions { long days = diff / org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis; out.months = (int) (days / org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); out.days = (int) (days % org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); - out.milliSeconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); + out.milliseconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); } } @@ -430,7 +431,7 @@ public class DateTypeFunctions { long days = diff / org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis; out.months = (int) (days / org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); out.days = (int) (days % org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); - out.milliSeconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); + out.milliseconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); } } @@ -453,7 +454,7 @@ public class DateTypeFunctions { long days = diff / org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis; out.months = (int) (days / org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); out.days = (int) (days % org.apache.drill.exec.expr.fn.impl.DateUtility.monthToStandardDays); - out.milliSeconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); + out.milliseconds = (int) (diff % org.apache.drill.exec.expr.fn.impl.DateUtility.daysToStandardMillis); } } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/HashFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/HashFunctions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/HashFunctions.java index 7475420..7c847eb 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/HashFunctions.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/HashFunctions.java @@ -460,7 +460,7 @@ public class HashFunctions { int xor = 0; for (int i = 0; i < in.nDecimalDigits; i++) { - xor = xor ^ in.getInteger(i); + xor = xor ^ Decimal28SparseHolder.getInteger(i, in.start, in.buffer); } out.value = com.google.common.hash.Hashing.murmur3_128().hashInt(xor).asInt(); } @@ -480,7 +480,7 @@ public class HashFunctions { else { int xor = 0; for (int i = 0; i < in.nDecimalDigits; i++) { - xor = xor ^ in.getInteger(i); + xor = xor ^ NullableDecimal28SparseHolder.getInteger(i, in.start, in.buffer); } out.value = com.google.common.hash.Hashing.murmur3_128().hashInt(xor).asInt(); } @@ -499,7 +499,7 @@ public class HashFunctions { int xor = 0; for (int i = 0; i < in.nDecimalDigits; i++) { - xor = xor ^ in.getInteger(i); + xor = xor ^ Decimal38SparseHolder.getInteger(i, in.start, in.buffer); } out.value = com.google.common.hash.Hashing.murmur3_128().hashInt(xor).asInt(); } @@ -519,7 +519,7 @@ public class HashFunctions { else { int xor = 0; for (int i = 0; i < in.nDecimalDigits; i++) { - xor = xor ^ in.getInteger(i); + xor = xor ^ NullableDecimal38SparseHolder.getInteger(i, in.start, in.buffer); } out.value = com.google.common.hash.Hashing.murmur3_128().hashInt(xor).asInt(); } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/SimpleCastFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/SimpleCastFunctions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/SimpleCastFunctions.java index 83c5540..8a09cff 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/SimpleCastFunctions.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/SimpleCastFunctions.java @@ -17,7 +17,9 @@ */ package org.apache.drill.exec.expr.fn.impl; -import io.netty.buffer.ByteBuf; +import io.netty.buffer.DrillBuf; + +import javax.inject.Inject; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; @@ -30,8 +32,9 @@ import org.apache.drill.exec.expr.holders.VarCharHolder; import org.apache.drill.exec.record.RecordBatch; public class SimpleCastFunctions { - public static final ByteBuf FALSE = org.apache.drill.exec.util.ByteBufUtil.createBuffer(new byte[] {'f', 'a', 'l', 's', 'e'}); - public static final ByteBuf TRUE = org.apache.drill.exec.util.ByteBufUtil.createBuffer(new byte[] {'t', 'r', 'u', 'e'}); + public static final byte[] TRUE = {'t','r','u','e'}; + public static final byte[] FALSE = {'f','a','l','s','e'}; + @FunctionTemplate(names = {"castBIT", "castBOOLEAN"}, scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) public static class CastVarCharBoolean implements DrillSimpleFunc { @@ -39,7 +42,9 @@ public class SimpleCastFunctions { @Param VarCharHolder in; @Output BitHolder out; - public void setup(RecordBatch b) {} + public void setup(RecordBatch b) { + + } public void eval() { byte[] buf = new byte[in.end - in.start]; @@ -61,14 +66,16 @@ public class SimpleCastFunctions { @Param BitHolder in; @Param BigIntHolder len; @Output VarCharHolder out; + @Inject DrillBuf buffer; public void setup(RecordBatch b) {} public void eval() { - io.netty.buffer.ByteBuf buffer = in.value == 1 ? org.apache.drill.exec.expr.fn.impl.SimpleCastFunctions.TRUE : org.apache.drill.exec.expr.fn.impl.SimpleCastFunctions.FALSE; + byte[] outB = in.value == 1 ? org.apache.drill.exec.expr.fn.impl.SimpleCastFunctions.TRUE : org.apache.drill.exec.expr.fn.impl.SimpleCastFunctions.FALSE; + buffer.setBytes(0, outB); out.buffer = buffer; out.start = 0; - out.end = Math.min((int)len.value, buffer.capacity()); // truncate if target type has length smaller than that of input's string + out.end = Math.min((int)len.value, outB.length); // truncate if target type has length smaller than that of input's string } } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/5c5cef06/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java new file mode 100644 index 0000000..68f7ca4 --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java @@ -0,0 +1,125 @@ +/******************************************************************************* + + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package org.apache.drill.exec.expr.fn.impl; + +import io.netty.buffer.DrillBuf; +import io.netty.util.internal.PlatformDependent; + +import org.joda.time.chrono.ISOChronology; + +import com.google.common.base.Charsets; + +public class StringFunctionHelpers { + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(StringFunctionHelpers.class); + + // Assumes Alpha as [A-Za-z0-9] + // white space is treated as everything else. + public static void initCap(int start, int end, DrillBuf inBuf, DrillBuf outBuf) { + boolean capNext = true; + + for (int id = start; id < end; id++) { + byte currentByte = inBuf.getByte(id); + + // 'A - Z' : 0x41 - 0x5A + // 'a - z' : 0x61 - 0x7A + // '0-9' : 0x30 - 0x39 + if (capNext) { // curCh is whitespace or first character of word. + if (currentByte >= 0x30 && currentByte <= 0x39) { // 0-9 + capNext = false; + } else if (currentByte >= 0x41 && currentByte <= 0x5A) { // A-Z + capNext = false; + } else if (currentByte >= 0x61 && currentByte <= 0x7A) { // a-z + capNext = false; + currentByte -= 0x20; // Uppercase this character + } + // else {} whitespace + } else { // Inside of a word or white space after end of word. + if (currentByte >= 0x30 && currentByte <= 0x39) { // 0-9 + // noop + } else if (currentByte >= 0x41 && currentByte <= 0x5A) { // A-Z + currentByte -= 0x20; // Lowercase this character + } else if (currentByte >= 0x61 && currentByte <= 0x7A) { // a-z + // noop + } else { // whitespace + capNext = true; + } + } + + outBuf.setByte(id, currentByte); + } // end of for_loop + } + + public static String toStringFromUTF8(int start, int end, DrillBuf buffer) { + byte[] buf = new byte[end - start]; + buffer.getBytes(start, buf, 0, end - start); + String s = new String(buf, Charsets.UTF_8); + return s; + } + + public static String toStringFromUTF16(int start, int end, DrillBuf buffer) { + byte[] buf = new byte[end - start]; + buffer.getBytes(start, buf, 0, end - start); + return new String(buf, Charsets.UTF_16); + } + + private static final ISOChronology CHRONOLOGY = org.joda.time.chrono.ISOChronology.getInstanceUTC(); + + public static long getDate(long memoryAddress, int start, int end){ + long index = memoryAddress + start; + final long endIndex = memoryAddress + end; + int digit = 0; + int radix = 10; // Base 10 digits + + // Stores three fields (year, month, day) + int[] dateFields = new int[3]; + int dateIndex = 0; + int value = 0; + + while (dateIndex < 3 && index < endIndex) { + digit = Character.digit(PlatformDependent.getByte(index++), radix); + + if (digit == -1) { + dateFields[dateIndex++] = value; + value = 0; + } else { + value = (value * 10) + digit; + } + } + + if (dateIndex < 3) { + // If we reached the end of input, we would have not encountered a separator, store the last value + dateFields[dateIndex++] = value; + } + + /* Handle two digit years + * Follow convention as done by Oracle, Postgres + * If range of two digits is between 70 - 99 then year = 1970 - 1999 + * Else if two digits is between 00 - 69 = 2000 - 2069 + */ + if (dateFields[0] < 100) { + if (dateFields[0] < 70) { + dateFields[0] += 2000; + } else { + dateFields[0] += 1900; + } + } + + return CHRONOLOGY.getDateTimeMillis(dateFields[0], dateFields[1], dateFields[2], 0); + } +}
