in java/clickhouse-client/src/main/java/com/epam/deltix/clickhouse/writer/WriterCodecGenerator.java [141:264]
private void processNested(MethodVisitor methodVisitor,
Class<?> nestedClass, String memberName,
String memberTypeDescriptor, SqlDataType dbDataType) {
String internalNestedName = Type.getInternalName(nestedClass);
List<ColumnDeclaration> columns = ((NestedDataType) dbDataType).getColumns();
loadMemberValueOnStack(methodVisitor, memberName, memberTypeDescriptor);
storeNestedMemberValue(methodVisitor);
loadNestedMemberOnStack(methodVisitor);
methodVisitor.visitMethodInsn(INVOKESTATIC, CodecUtil.INTERNAL_NAME, CodecUtil.MAKE_LIST_NOT_NULL_NAME, CodecUtil.MAKE_LIST_NOT_NULL_DESC, false);
storeNestedMemberValue(methodVisitor);
loadNestedMemberOnStack(methodVisitor);
// invoke size() method on a `memberName`
methodVisitor.visitMethodInsn(INVOKEINTERFACE, INTERNAL_LIST_NAME, "size", "()I", true);
storeSizeOfNestedMemberValue(methodVisitor);
List<String> arrayDescriptors = new ArrayList<>();
List<BindDeclaration> nestedBinds;
if (IntrospectionType.BY_GETTERS == introspectionType)
nestedBinds = BindHelper.getBindDeclarationsByGetMethods(nestedClass, columns);
else
nestedBinds = BindHelper.getBindDeclarationsByFields(nestedClass, columns);
int currentLocalVarIndex = 7;
for (BindDeclaration bind : nestedBinds) {
Class<?> nestedType = BindHelper.memberType.apply(bind);
String nestedInternalName = Type.getInternalName(nestedType);
arrayDescriptors.add(String.format("[%s", Type.getDescriptor(nestedType)));
currentLocalVarIndex = initArray(methodVisitor, nestedType, nestedInternalName, currentLocalVarIndex);
}
Label start = new Label();
Label loop = new Label();
methodVisitor.visitLabel(start);
methodVisitor.visitInsn(ICONST_0);
int tempVarIndex = currentLocalVarIndex;
// it is 'index' in 'for' loop.
methodVisitor.visitVarInsn(ISTORE, tempVarIndex);
localVarSize++;
methodVisitor.visitLabel(loop);
// '+ 1' need, because 'this' reference is also local variable.
int numLocal = tempVarIndex + 1;
Object[] localVariableTypes = getLocalVarTypes(arrayDescriptors, numLocal);
methodVisitor.visitFrame(F_FULL, numLocal, localVariableTypes, 0, new Object[]{});
methodVisitor.visitVarInsn(ILOAD, tempVarIndex);
loadSizeOfNestedMemberValueOnStack(methodVisitor);
Label l6 = new Label();
methodVisitor.visitJumpInsn(IF_ICMPGE, l6);
Label l7 = new Label();
methodVisitor.visitLabel(l7);
currentLocalVarIndex = 7;
for (BindDeclaration bind : nestedBinds) {
String nestedName = BindHelper.memberName.apply(bind);
Class<?> nestedType = BindHelper.memberType.apply(bind);
String nestedTypeDescriptor = BindHelper.memberDescriptor.apply(bind);
methodVisitor.visitVarInsn(ALOAD, currentLocalVarIndex++);
methodVisitor.visitVarInsn(ILOAD, tempVarIndex);
loadNestedMemberOnStack(methodVisitor);
methodVisitor.visitVarInsn(ILOAD, tempVarIndex);
methodVisitor.visitMethodInsn(INVOKEINTERFACE, INTERNAL_LIST_NAME, "get", "(I)Ljava/lang/Object;", true);
methodVisitor.visitTypeInsn(CHECKCAST, internalNestedName);
loadNestedMemberValueOnStack(methodVisitor, internalNestedName, nestedName, nestedTypeDescriptor);
if (!nestedType.isPrimitive())
methodVisitor.visitInsn(AASTORE);
else if (nestedType.equals(long.class))
methodVisitor.visitInsn(LASTORE);
else if (nestedType.equals(int.class))
methodVisitor.visitInsn(IASTORE);
else if (nestedType.equals(short.class))
methodVisitor.visitInsn(SASTORE);
else if (nestedType.equals(float.class))
methodVisitor.visitInsn(FASTORE);
else if (nestedType.equals(double.class))
methodVisitor.visitInsn(DASTORE);
else if (nestedType.equals(byte.class) ||
nestedType.equals(boolean.class))
methodVisitor.visitInsn(BASTORE);
}
Label l8 = new Label();
methodVisitor.visitLabel(l8);
methodVisitor.visitIincInsn(tempVarIndex, 1);
methodVisitor.visitJumpInsn(GOTO, loop);
methodVisitor.visitLabel(l6);
methodVisitor.visitFrame(F_CHOP, 1, null, 0, null);
currentLocalVarIndex = 7;
for (BindDeclaration bind : nestedBinds) {
Class<?> nestedType = BindHelper.memberType.apply(bind);
ClickHouseDataType sqlType = CodecUtil.getClickHouseDataType(nestedType);
loadPsOnStack(methodVisitor);
loadParameterIndexOnStack(methodVisitor);
methodVisitor.visitVarInsn(ALOAD, currentLocalVarIndex++);
String owner = Type.getInternalName(ClickHouseDataType.class);
String value = sqlType.name();
String descriptor = Type.getDescriptor(ClickHouseDataType.class);
methodVisitor.visitFieldInsn(GETSTATIC, owner, value, descriptor);
methodVisitor.visitMethodInsn(INVOKESTATIC, CodecUtil.INTERNAL_NAME, CodecUtil.PROCESS_ARRAY_NAME, CodecUtil.PROCESS_ARRAY_DESC, false);
storeParameterIndexValue(methodVisitor);
}
}