コード例 #1
0
  private void generateFilterMethod(
      CallSiteBinder callSiteBinder,
      ClassDefinition classDefinition,
      RowExpression filter,
      boolean sourceIsCursor) {
    MethodDefinition filterMethod;
    if (sourceIsCursor) {
      filterMethod =
          classDefinition.declareMethod(
              new CompilerContext(BOOTSTRAP_METHOD),
              a(PUBLIC),
              "filter",
              type(boolean.class),
              arg("cursor", RecordCursor.class));
    } else {
      filterMethod =
          classDefinition.declareMethod(
              new CompilerContext(BOOTSTRAP_METHOD),
              a(PUBLIC),
              "filter",
              type(boolean.class),
              ImmutableList.<NamedParameterDefinition>builder()
                  .add(arg("position", int.class))
                  .addAll(toBlockParameters(getInputChannels(filter)))
                  .build());
    }

    filterMethod.comment("Filter: %s", filter.toString());

    filterMethod.getCompilerContext().declareVariable(type(boolean.class), "wasNull");
    Block getSessionByteCode =
        new Block(filterMethod.getCompilerContext())
            .pushThis()
            .getField(classDefinition.getType(), "session", type(ConnectorSession.class));
    ByteCodeNode body =
        compileExpression(
            callSiteBinder,
            filter,
            sourceIsCursor,
            filterMethod.getCompilerContext(),
            getSessionByteCode);

    LabelNode end = new LabelNode("end");
    filterMethod
        .getBody()
        .comment("boolean wasNull = false;")
        .putVariable("wasNull", false)
        .append(body)
        .getVariable("wasNull")
        .ifFalseGoto(end)
        .pop(boolean.class)
        .push(false)
        .visitLabel(end)
        .retBoolean();
  }
コード例 #2
0
  private MethodDefinition generateProjectMethod(
      ClassDefinition classDefinition,
      CallSiteBinder callSiteBinder,
      CachedInstanceBinder cachedInstanceBinder,
      String methodName,
      RowExpression projection) {
    Parameter session = arg("session", ConnectorSession.class);
    List<Parameter> inputs = toBlockParameters(getInputChannels(projection));
    Parameter position = arg("position", int.class);
    Parameter output = arg("output", BlockBuilder.class);
    MethodDefinition method =
        classDefinition.declareMethod(
            a(PUBLIC),
            methodName,
            type(void.class),
            ImmutableList.<Parameter>builder()
                .add(session)
                .addAll(inputs)
                .add(position)
                .add(output)
                .build());

    method.comment("Projection: %s", projection.toString());

    Scope scope = method.getScope();
    BytecodeBlock body = method.getBody();

    Variable wasNullVariable = scope.declareVariable("wasNull", body, constantFalse());
    BytecodeExpressionVisitor visitor =
        new BytecodeExpressionVisitor(
            callSiteBinder,
            cachedInstanceBinder,
            fieldReferenceCompiler(callSiteBinder, position, wasNullVariable),
            metadata.getFunctionRegistry());

    body.getVariable(output)
        .comment("evaluate projection: " + projection.toString())
        .append(projection.accept(visitor, scope))
        .append(generateWrite(callSiteBinder, scope, wasNullVariable, projection.getType()))
        .ret();
    return method;
  }
コード例 #3
0
  private static void generateFilterPageMethod(
      ClassDefinition classDefinition, RowExpression filter) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);

    MethodDefinition method =
        classDefinition.declareMethod(a(PUBLIC), "filterPage", type(int[].class), session, page);
    method.comment("Filter: %s rows in the page", filter.toString());

    Scope scope = method.getScope();
    Variable thisVariable = method.getThis();
    BytecodeBlock body = method.getBody();

    Variable positionCount =
        scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
    Variable selectedPositions =
        scope.declareVariable(
            "selectedPositions", body, newArray(type(int[].class), positionCount));

    List<Integer> filterChannels = getInputChannels(filter);

    // extract block variables
    ImmutableList.Builder<Variable> blockVariablesBuilder = ImmutableList.<Variable>builder();
    for (int channel : filterChannels) {
      Variable blockVariable =
          scope.declareVariable(
              "block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
      blockVariablesBuilder.add(blockVariable);
    }
    List<Variable> blockVariables = blockVariablesBuilder.build();

    Variable selectedCount = scope.declareVariable("selectedCount", body, constantInt(0));
    Variable position = scope.declareVariable(int.class, "position");

    IfStatement ifStatement = new IfStatement();
    ifStatement
        .condition(invokeFilter(thisVariable, session, blockVariables, position))
        .ifTrue()
        .append(selectedPositions.setElement(selectedCount, position))
        .append(selectedCount.increment());

    body.append(
        new ForLoop()
            .initialize(position.set(constantInt(0)))
            .condition(lessThan(position, positionCount))
            .update(position.increment())
            .body(ifStatement));

    body.append(
        invokeStatic(Arrays.class, "copyOf", int[].class, selectedPositions, selectedCount).ret());
  }
コード例 #4
0
  private void generateFilterMethod(
      ClassDefinition classDefinition,
      CallSiteBinder callSiteBinder,
      CachedInstanceBinder cachedInstanceBinder,
      RowExpression filter) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter position = arg("position", int.class);

    List<Parameter> blocks = toBlockParameters(getInputChannels(filter));
    MethodDefinition method =
        classDefinition.declareMethod(
            a(PUBLIC),
            "filter",
            type(boolean.class),
            ImmutableList.<Parameter>builder().add(session).addAll(blocks).add(position).build());

    method.comment("Filter: %s", filter.toString());
    BytecodeBlock body = method.getBody();

    Scope scope = method.getScope();
    Variable wasNullVariable = scope.declareVariable("wasNull", body, constantFalse());

    BytecodeExpressionVisitor visitor =
        new BytecodeExpressionVisitor(
            callSiteBinder,
            cachedInstanceBinder,
            fieldReferenceCompiler(callSiteBinder, position, wasNullVariable),
            metadata.getFunctionRegistry());
    BytecodeNode visitorBody = filter.accept(visitor, scope);

    Variable result = scope.declareVariable(boolean.class, "result");
    body.append(visitorBody)
        .putVariable(result)
        .append(
            new IfStatement()
                .condition(wasNullVariable)
                .ifTrue(constantFalse().ret())
                .ifFalse(result.ret()));
  }
コード例 #5
0
  private Class<?> generateProjectMethod(
      CallSiteBinder callSiteBinder,
      ClassDefinition classDefinition,
      String methodName,
      RowExpression projection,
      boolean sourceIsCursor) {
    MethodDefinition projectionMethod;
    if (sourceIsCursor) {
      projectionMethod =
          classDefinition.declareMethod(
              new CompilerContext(BOOTSTRAP_METHOD),
              a(PUBLIC),
              methodName,
              type(void.class),
              arg("cursor", RecordCursor.class),
              arg("output", BlockBuilder.class));
    } else {
      ImmutableList.Builder<NamedParameterDefinition> parameters = ImmutableList.builder();
      parameters.add(arg("position", int.class));
      parameters.addAll(toBlockParameters(getInputChannels(projection)));
      parameters.add(arg("output", BlockBuilder.class));

      projectionMethod =
          classDefinition.declareMethod(
              new CompilerContext(BOOTSTRAP_METHOD),
              a(PUBLIC),
              methodName,
              type(void.class),
              parameters.build());
    }

    projectionMethod.comment("Projection: %s", projection.toString());

    // generate body code
    CompilerContext context = projectionMethod.getCompilerContext();
    context.declareVariable(type(boolean.class), "wasNull");
    Block getSessionByteCode =
        new Block(context)
            .pushThis()
            .getField(classDefinition.getType(), "session", type(ConnectorSession.class));

    ByteCodeNode body =
        compileExpression(callSiteBinder, projection, sourceIsCursor, context, getSessionByteCode);

    projectionMethod
        .getBody()
        .comment("boolean wasNull = false;")
        .putVariable("wasNull", false)
        .getVariable("output")
        .append(body);

    Type projectionType = projection.getType();
    Block notNullBlock = new Block(context);
    if (projectionType.getJavaType() == boolean.class) {
      notNullBlock
          .comment("output.append(<booleanStackValue>);")
          .invokeInterface(BlockBuilder.class, "appendBoolean", BlockBuilder.class, boolean.class)
          .pop();
    } else if (projectionType.getJavaType() == long.class) {
      notNullBlock
          .comment("output.append(<longStackValue>);")
          .invokeInterface(BlockBuilder.class, "appendLong", BlockBuilder.class, long.class)
          .pop();
    } else if (projectionType.getJavaType() == double.class) {
      notNullBlock
          .comment("output.append(<doubleStackValue>);")
          .invokeInterface(BlockBuilder.class, "appendDouble", BlockBuilder.class, double.class)
          .pop();
    } else if (projectionType.getJavaType() == Slice.class) {
      notNullBlock
          .comment("output.append(<sliceStackValue>);")
          .invokeInterface(BlockBuilder.class, "appendSlice", BlockBuilder.class, Slice.class)
          .pop();
    } else {
      throw new UnsupportedOperationException("Type " + projectionType + " can not be output yet");
    }

    Block nullBlock =
        new Block(context)
            .comment("output.appendNull();")
            .pop(projectionType.getJavaType())
            .invokeInterface(BlockBuilder.class, "appendNull", BlockBuilder.class)
            .pop();

    projectionMethod
        .getBody()
        .comment("if the result was null, appendNull; otherwise append the value")
        .append(
            new IfStatement(
                context, new Block(context).getVariable("wasNull"), nullBlock, notNullBlock))
        .ret();

    return projectionType.getJavaType();
  }