private static BytecodeExpression invokeFilter( BytecodeExpression objRef, BytecodeExpression session, List<? extends BytecodeExpression> blockVariables, BytecodeExpression position) { List<BytecodeExpression> params = ImmutableList.<BytecodeExpression>builder() .add(session) .addAll(blockVariables) .add(position) .build(); return objRef.invoke("filter", boolean.class, params); }
private static MethodDefinition generateProjectDictionaryMethod( ClassDefinition classDefinition, String methodName, RowExpression projection, MethodDefinition project, MethodDefinition projectColumnar) { Parameter session = arg("session", ConnectorSession.class); Parameter page = arg("page", Page.class); Parameter selectedPositions = arg("selectedPositions", int[].class); Parameter pageBuilder = arg("pageBuilder", PageBuilder.class); Parameter projectionIndex = arg("projectionIndex", int.class); List<Parameter> params = ImmutableList.<Parameter>builder() .add(session) .add(page) .add(selectedPositions) .add(pageBuilder) .add(projectionIndex) .build(); MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), methodName, type(Block.class), params); BytecodeBlock body = method.getBody(); Scope scope = method.getScope(); Variable thisVariable = method.getThis(); List<Integer> inputChannels = getInputChannels(projection); if (inputChannels.size() != 1) { body.append(thisVariable.invoke(projectColumnar, params).ret()); return method; } Variable inputBlock = scope.declareVariable( "inputBlock", body, page.invoke( "getBlock", Block.class, constantInt(Iterables.getOnlyElement(inputChannels)))); IfStatement ifStatement = new IfStatement() .condition(inputBlock.instanceOf(DictionaryBlock.class)) .ifFalse(thisVariable.invoke(projectColumnar, params).ret()); body.append(ifStatement); Variable blockBuilder = scope.declareVariable( "blockBuilder", body, pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, projectionIndex)); Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length()); Variable dictionary = scope.declareVariable(Block.class, "dictionary"); Variable ids = scope.declareVariable(Slice.class, "ids"); Variable dictionaryCount = scope.declareVariable(int.class, "dictionaryCount"); Variable outputDictionary = scope.declareVariable(Block.class, "outputDictionary"); Variable outputIds = scope.declareVariable(int[].class, "outputIds"); BytecodeExpression inputDictionaries = thisVariable.getField("inputDictionaries", Block[].class); BytecodeExpression outputDictionaries = thisVariable.getField("outputDictionaries", Block[].class); Variable position = scope.declareVariable("position", body, constantInt(0)); body.comment("Extract dictionary and ids") .append( dictionary.set( inputBlock.cast(DictionaryBlock.class).invoke("getDictionary", Block.class))) .append(ids.set(inputBlock.cast(DictionaryBlock.class).invoke("getIds", Slice.class))) .append(dictionaryCount.set(dictionary.invoke("getPositionCount", int.class))); BytecodeBlock projectDictionary = new BytecodeBlock() .comment("Project dictionary") .append( new ForLoop() .initialize(position.set(constantInt(0))) .condition(lessThan(position, dictionaryCount)) .update(position.increment()) .body( invokeProject( thisVariable, session, ImmutableList.of(dictionary), position, pageBuilder, projectionIndex, project))) .append(outputDictionary.set(blockBuilder.invoke("build", Block.class))) .append(inputDictionaries.setElement(projectionIndex, dictionary)) .append(outputDictionaries.setElement(projectionIndex, outputDictionary)); body.comment("Use processed dictionary, if available, else project it") .append( new IfStatement() .condition(equal(inputDictionaries.getElement(projectionIndex), dictionary)) .ifTrue(outputDictionary.set(outputDictionaries.getElement(projectionIndex))) .ifFalse(projectDictionary)); body.comment("Filter ids") .append(outputIds.set(newArray(type(int[].class), cardinality))) .append( new ForLoop() .initialize(position.set(constantInt(0))) .condition(lessThan(position, cardinality)) .update(position.increment()) .body( outputIds.setElement( position, ids.invoke( "getInt", int.class, multiply( selectedPositions.getElement(position), constantInt(SIZE_OF_INT)))))); body.append( newInstance( DictionaryBlock.class, cardinality, outputDictionary, invokeStatic(Slices.class, "wrappedIntArray", Slice.class, outputIds)) .cast(Block.class) .ret()); return method; }